c# - 使用 asp.net-mvc2 和 Entity Framework 编辑和更新复杂 View 模型对象的正确方法

标签 c# asp.net entity-framework asp.net-mvc-2

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

父对象

  • 身份证
  • 姓名
  • 描述

子对象

  • 身份证
  • 姓名
  • 描述
  • 父对象ID
  • 另一个对象ID

另一个对象

  • 身份证
  • 姓名

对象被映射到 Entity Framework 并通过数据访问类公开。

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

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

我有一个显示 ParentObjects 列表的 View ,单击时将允许修改保存的 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;
    }
}

这似乎工作正常。我想问你们好人:有没有正确的方法来做到这一点?我尝试按照我在上面发布的博客链接制作自定义模型 Binder 的建议,但它没有用(反射存在问题,代码期望某些属性存在)并且我需要尽快完成一些事情。

PS - 我试图清理代码以隐藏特定信息,所以请注意我可能已经清理了一些东西。我主要是想知道其他人有没有解决这个问题。

最佳答案

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

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

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

关于c# - 使用 asp.net-mvc2 和 Entity Framework 编辑和更新复杂 View 模型对象的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2569465/

相关文章:

asp.net - 为什么request.rawurl不包含http ://localhost part?

entity-framework - EF 代码首先告诉我对已经存在于数据库中的数据库对象进行迁移

c# - C#和Flex之间的套接字通信问题

c# - 使用 C# 创建 Autocad 文件

c# - 使用 MongoDB 和 ASP.NET MVC 构建 Web 应用程序,我应该使用 C# 驱动程序还是 Javascript 驱动程序

c# - 如何捕获整个查询字符串?

c# - C# smtp.gmail.com 和端口号 587 中目标主机拒绝发送电子邮件

wpf - EF5 和 DB2 9.1。 bool 未定义类型错误

c# - 从 EntityFramework 的 `DbContext` 获取数据库类型

c# - 获取类<T>的一般类型使用类型的类型