c# – 使用asp.net-mvc2和实体框架编辑和更新复杂viewmodel对象的正确方法

我的数据库中有一个表与另一个表的一对多关系,它与第三个表有关系:

ParentObject

> ID
>姓名
>说明

ChildObject

> ID
>姓名
>说明
> ParentObjectID
> AnotherObjectID
    

AnotherObject

> ID
>姓名

对象映射到实体框架并通过数据访问类公开.

当要显示的数据与域对象有很大不同时,建议使用ViewModel,因此我创建了一个ViewModel,如下所示:

public class ViewModel {
    public IList<ParentObject> ParentObjects { get; set; }
    public ParentObject selectedObject { get; set; }
    public IList<ChildObject> ChildObjects { get; set; }
}

我有一个显示ParentObjects列表的视图,当单击时将允许保存ChildObject.

<% using (Html.BeginForm()) { %> 
<table>
    <% foreach (var parent in Model.ParentObjects) { %>
    <tr>
        <td>
            ObjectID [<%= Html.Encode(parent.ID)%>]
        </td>
        <td>
            <%= Html.Encode(parent.Name)%>
        </td>
        <td>
            <%= Html.Encode(parent.Description)%>
        </td>
    </tr>
    <% } %>
</table>
<% if (Model.ParentObject != null) { %>
<div>
    Name:<br />
    <%= Html.TextBoxFor(model => model.ParentObject.Name) %>
    <%= Html.ValidationMessageFor(model => model.ParentObject.Name, "*")%>
</div>
<div>
    Description:<br />
    <%= Html.TextBoxFor(model => model.ParentObject.Description) %>
    <%= Html.ValidationMessageFor(model => model.ParentObject.Description, "*")%>
</div>
<div>
    Child Objects
</div>
<% for (int i = 0; i < Model.ParentObject.ChildObjects.Count(); i++) { %>
    <div>
        <%= Html.DisplayTextFor(sd => sd.ChildObjects[i].Name) %>
    </div>
    <div>
        <%= Html.HiddenFor(sd => sd.ChildObjects[i].ID )%>
        <%= Html.TextBoxFor( sd => sd.ChildObjects[i].Description) %>
        <%= Html.ValidationMessageFor(sd => sd.ChildObjects[i].Description, "*") %>
    </div>
    <% }
}
} %>

一切正常.我的问题是更新EF对象并将更改保留回数据库的最佳方法.我最初尝试过:

[HttpPost]
    public ActionResult Edit(ViewModel viewModel) {
        ParentObject parent = myRepository.GetParentObjectByID(viewModel.SelectedObject.ID);

        if ((!ModelState.IsValid)
            || !TryUpdateModel(parent, "SelectedObject", new[] { "Name", "Description" })) {
            || !TryUpdateModel(parent.ChildObjects, "ChildObjects", new[] { "Name", "Description" })) {


            //Code to handle failure and return the current model snipped

            return View(viewModel);
        }

        myRepository.Save();

        return RedirectToAction("Edit");
    }

当我尝试将更改保存到子对象时,我得到此异常:“MyEntities.ChildObject”中的实体参与“FK_ChildObject_AnotherObject”关系.找到0个相关的’AnotherObject’. 1’AnotherObject’是预期的.

对StackOverflow和一般谷歌搜索的调查使我看到了this blog post似乎描述了我的问题:TryUpdateModel()没有正确处理嵌套集合.显然,(并通过调试器逐步确认)它创建了一个新的ChildObject,而不是与我实例化的上下文中的EF对象相关联.

我的hacky工作是这样的:

if (viewModel.ChildObjects.Count > 0) {
    foreach (ChildObject modelChildObject in viewModel.ChildObjects) {
        ChildObject childToUpdate = ParentObject.ChildObject.Where(a => a.ID == modelChildObject.ID).First();
        childToUpdate.Name = modelChildObject.Name;
    }
}

这似乎工作正常.我向你问好的人:有没有正确的方法来做到这一点?我尝试按照上面发布的博客链接制作自定义模型绑定器的建议,但它不起作用(反射存在问题,代码期望某些属性存在),我需要尽快得到一些东西.

PS – 我试图清理代码以隐藏特定信息,所以要小心我可能已经有些东西了.我主要想知道其他人是否已经解决了这个问题.

只是简单地看一下提到FK_ChildObject_AnotherObject的错误…你确定在关于AnotherObject的EF数据模型中所有内容都正确连接了吗?

在您的问题中,您只列出了两个表,但此错误表明ChildObject正在与AnotherObject参与1到*的关系,并且在保存时实体中没有一个存在导致错误.

尝试从情境中删除AnotherObject以测试ParentObject和ChildObject之间的任何假设问题,或者尝试将FK_ChildObject_AnotherObject关系简单地更改为0..1到*以进行测试.

相关文章
相关标签/搜索