代码之家  ›  专栏  ›  技术社区  ›  jslatts

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

  •  8
  • jslatts  · 技术社区  · 14 年前

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

    父对象

    • 身份证件
    • 名称
    • 描述

    子对象

    • 名称
    • 描述
    • 另一个目标ID

    另一个对象

    • 名称

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

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

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

    <% 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\u ChildObject\u AnotherObject“关系。找到0个相关的“AnotherObject”。应为1“AnotherObject”。

    对StackOverflow和谷歌搜索的调查让我找到了 this blog post 这似乎描述了我的问题:TryUpdateModel()不能正确处理嵌套集合。显然,(通过调试器确认这一点)它创建了一个新的子对象,而不是从实例化的上下文中与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-我试图清理代码以隐藏特定信息,因此请注意,我可能已经用软管堵塞了某些信息。我主要只是想知道其他人是否解决了这个问题。

    2 回复  |  直到 14 年前
        1
  •  1
  •   user308105    14 年前

    只是简单地看一下提到FK\u ChildObject\u AnotherObject的错误。。。你确定你的EF数据模型中关于另一个对象的一切都连接正确了吗?

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

        2
  •  0
  •   DanH    13 年前

    tbh不完全清楚这里的原始问题。我不知道为什么viewmodel中的子对象首先要从父对象分离?