【问题标题】:ASP.NET MVC 2: Updating a Linq-To-Sql Entity with an EntitySetASP.NET MVC 2:使用 EntitySet 更新 Linq-To-Sql 实体
【发布时间】:2010-03-30 21:09:42
【问题描述】:

我有一个具有 EntitySet 的 Linq to Sql 实体。在我的视图中,我显示实体及其属性以及子实体的可编辑列表。用户可以动态添加和删除这些子实体。到目前为止,DefaultModelBinder 工作正常,它正确绑定了子实体。

现在我的问题是我无法让 Linq To Sql 删除已删除的子实体,它会很高兴地添加新实体但不会删除已删除的实体。我在外键关系中启用了级联删除,Linq To Sql 设计器在外键关系中添加了“DeleteOnNull=true”属性。如果我像这样手动删除一个子实体:

myObject.Childs.Remove(child);
context.SubmitChanges();

这将从数据库中删除子记录。 但我无法让它适用于模型绑定对象。我尝试了以下方法:

// this does nothing
public ActionResult Update(int id, MyObject obj) // obj now has 4 child entities
{
    var obj2 = _repository.GetObj(id); // obj2 has 6 child entities
    if(TryUpdateModel(obj2)) //it sucessfully updates obj2 and its childs
    {
         _repository.SubmitChanges(); // nothing happens, records stay in DB
    }
    else
         .....

    return RedirectToAction("List");
}

这会引发 InvalidOperationException,我有一个德语操作系统,所以我不确定错误消息是什么英文,但它说的是实体需要一个版本(时间戳行?)或否更新检查政策。我已将 UpdateCheck="Never" 设置为除主键列之外的每一列。

public ActionResult Update(MyObject obj)
{
    _repository.MyObjectTable.Attach(obj, true);
    _repository.SubmitChanges(); // never gets here, exception at attach
}

我读过很多关于 Linq To Sql 的类似“问题”,但似乎大多数“问题”实际上是设计使然。那么我的假设是否正确,这不像我期望的那样起作用?我真的必须手动遍历子实体并手动删除、更新和插入它们吗?对于这样一个简单的对象,这可能会起作用,但我计划使用嵌套的 EntitySet 等创建更复杂的对象。这只是一个测试,看看什么有效,什么无效。到目前为止,我对 Linq To Sql 感到失望(也许我只是不明白)。对于这种情况,Entity Framework 或 NHibernate 会是更好的选择吗?还是我会遇到同样的问题?

【问题讨论】:

  • 您介意分享德语文本吗?
  • 当然!异常消息是:“Eine Entität kann nur als geändert und ohne den ursprünglichen Zusand angefügt werden, wenn sie ein Versionselement deklariert oder über keine Richtlinie für die Überprüfung auf Updates verfügt。”
  • 这种情况总是发生,还是仅在您使用 .Attach 时发生?

标签: asp.net-mvc linq-to-sql modelbinders


【解决方案1】:

它肯定可以在 .NET 4 附带的实体框架中工作(我在 RC 版本中做类似的事情)

这并不能解释异常但是

您应该处置(最有可能)包装在您的存储库中的ObjectContext。上下文缓存项目,并且只能用于单个工作单元。

尝试使用如下模式:

public ActionResult Update(int id, MyObject obj) // obj now has 4 child entities
{
    using(var repository = CreateRepository())
    {
        var obj2 = _repository.GetObj(id);
        if(TryUpdateModel(obj2))
        {
             repository.SubmitChanges();
        }
        else
            .....
    }

    return RedirectToAction("List");
}

在获取项目时,也要创建一个新的存储库。它们的创建和处置成本低廉,应尽快处置。

【讨论】:

  • 目前我正在控制器的构造函数中创建存储库,所以我希望它只适用于单个请求,还是我错了?控制器寿命更长吗? (我刚刚开始使用 MVC 和 LinqToSql)我在操作中使用 using 语句进行了尝试,但奇怪的是它不断为子对象添加新记录。我会继续调查。到目前为止谢谢!
  • 好点,添加一些断点:创建存储库的位置,.Update.List。如果构造函数没有执行两次,则可能有问题。
  • 好的,我刚刚检查了这个,并且正在为每个请求创建存储库
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 2011-11-09
  • 1970-01-01
  • 2016-10-20
相关资源
最近更新 更多