EF,MVC,模型绑定和导航属性

时间:2012-08-31 16:51:48

标签: asp.net-mvc entity-framework model-binding

我正在使用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,不使用viewmodel类 - 可能是一个错误?,但管道代码少得多)。在我看来,我使用HiddenFor for Scenario.Id和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,这当然是件坏事
  • 名称设为null

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

2 个答案:

答案 0 :(得分:0)

您不应该在更新中从数据库获取scenario。相反,您应该采用绑定模型,附加它(如果已编辑)或将其添加(如果是新的)上下文,然后保存更改。这是一个常见的场景,称为&#34;断开连接的实体&#34; (事实上​​,你确实有这种情况,因为你的模型在发送给客户端时已断开连接,然后又恢复了连接)。

答案 1 :(得分:0)

  1. 我“修复”了DefaultModelBinder / UpdateCollection,以便它可以使用我的用例:当导航属性中的绑定向下钻取时,它使用当前对象作为模型(这很容易,因为我只做了修改,没有插入或删除):我可以使用DefaultModel源代码,将我的修复程序放入其中,并将其用作自定义模型绑定器。这很有趣,但有点脏,而且超过顶部。
  2. 但我认为最好的方法是使用特定的ViewModel,仅使用可编辑的属性,并使用AutoMap将其映射到我的EF层次结构。但是:它具有创建子对象集合的相同问题。
  3. 最后,我只是在我的View Model和我的EF层次结构之间进行了一些手动映射:我几乎可以确定我可以自动执行某些操作,这可以检测子项是否已被修改或插入或删除(从那以后)每个项目都有[key]属性,但我没有时间预算来实现它。