繁体   English   中英

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

[英]Correct way to edit and update complex viewmodel objects using asp.net-mvc2 and entity framework

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

父对象

  • ID
  • 名称
  • 描述

子对象

  • ID
  • 名称
  • 描述
  • ParentObjectID
  • AnotherObjectID

另一个对象

  • ID
  • 名称

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

当要显示的数据与域对象有很大差异时,似乎建议使用ViewModels,因此我按如下方式创建了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和常规搜索的调查使我转向了这篇博客文章该文章似乎描述了我的问题:TryUpdateModel()无法正确处理嵌套集合。 显然,(并逐步通过调试器确认了这一点)它将创建一个新的ChildObject,而不是与我实例化的上下文中的EF对象关联。

我的变通方法是这样的:

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短暂更改为*以进行测试。

您可以看看使用Omu ValueInjector而不是tryupdate。 尽管我更喜欢按惯例使用它,但它可以配置为更加智能。

在这里对原始问题还不完全清楚。 我不确定为什么首先将视图模型中的子对象与父对象分离?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM