0

我正在使用 EF5 Code First:

public class Scenario
{
    public int Id { get; set; }
    public  IList<Client> Clients { get; set; }
}
public class Client
{
    public int Id { get; set; }
    public string Name {get;set;}
    public int VisibilityNumber{ get; set; }
}

我直接将场景对象发送到视图(MVC4,不使用视图模型类 - 可能是一个错误?,但管道代码少了很多)。在我看来,我对 Scenario.Id 使用 HiddenFor,并使用 for 循环为每个客户端 VisibilityNumber 显示一个 EditFor。

这是控制器:

[HttpPost]
public ActionResult Edit(int id, FormCollection formValues)
{     
if (ModelState.IsValid)
    {
        Scenario scen=GetScenarioFromDB(id);
        TryUpdateModel(scen,formValues);
        if (ModelState.IsValid)
           SaveToDb(scen);
    }
}

在 TryUpdateModel 之后,对于每个 Clients 对象(从 DB 中正确加载):

  • VisibilityNumber 设置正确
  • id设置为0,当然是坏事
  • 名称设置为空

查看 MVC 源代码(DefaultModelBinder/UpdateCollection)后,我可以看到在绑定到集合时,总是会创建新项目。如果我不能解决这个问题,我想我将使用 viewModel 和 AutoMapper。我假设 MVC 团队想强迫我们使用 viewModel,而不是直接发送 EF 对象。

4

2 回答 2

0

您不应该scenario在更新中从数据库中获取。相反,您应该获取绑定模型,将其附加(如果已编辑)或将其添加(如果新)到上下文中,然后保存更改。这是一种称为“断开连接的实体”的常见场景(实际上,您确实有,因为您的模型在发送到客户端时断开连接,然后返回也断开连接)。

于 2012-08-31T18:55:24.147 回答
0
  1. 我“修复”了 DefaultModelBinder/UpdateCollection 以便它可以与我的用例一起使用:当绑定在导航属性中向下钻取时,它使用当前对象作为模型(这很容易,因为我只进行修改,没有插入或delete) :我可以获取 DefaultModel 源代码,将我的修复程序放入其中,并将其用作自定义模型绑定器。这很有趣,但有点脏而且过头了。
  2. 但我相信最好的方法是使用特定的 ViewModel,仅使用可编辑的属性,并使用 AutoMap 将其映射到我的 EF 层次结构。但是:它具有创建子对象集合的相同问题。
  3. 最后,我只是在我的视图模型和我的 EF 层次结构之间进行了一些手动映射:我几乎可以肯定我可以做一些自动的事情,它可以检测一个子项目是否被修改、插入或删除(因为每个项目都有一个 [key] 属性,但我没有时间预算来实施它。
于 2012-08-31T23:33:09.853 回答