繁体   English   中英

数据上下文的SubmitChanges方法使实体引用设置为null

[英]Data Context's SubmitChanges method causing a entity reference to be set to null

我知道这看起来有点长,但我试图尽可能地解释这个问题。

我们对linq to sql数据上下文类有一个非常“异乎寻常”的问题。 我们有一个n层结构,结构如下:我们有3个类MotherClass,ChildClass,ChildChildrenClass

MotherClass看起来像这样:

public class MotherClass
{
     private EntitySet<ChildClass> _Children;

     [Column]
     public int Id { get; set; }

     [Association(Storage = "_Children", ThisKey = "Id", OtherKey = "MotherId")]
     public EntitySet<ChildClass> Children
     {
           get { return _Children; }
           set { _Children= value; }
     }
}

而ChildClass看起来像:

public class ChildClass
{
     private EntityRef<MotherClass> _Mother;
     private EntitySet<ChildChildrenClass> _ChildChildren;

     [Column]
     public int Id { get; set; }

     [Column]
     public int MotherId { get; set; }

     [Association(Storage = "_Mother", IsForeignKey = true, ThisKey = "MotherId", OtherKey = "Id")]
     public MotherClass Mother
     {
           get { return _Mother.Entity; }
           set { _Mother.Entity = value; }
     }

     [Association(Storage = "_ChildChildren", ThisKey = "Id", OtherKey = "ChildId", DeleteRule = "NO ACTION")]
     public EntitySet<ChildChildrenClass> ChildChildren
     {
           get { return _ChildChildren; }
           set { _ChildChildren= value; }
     }
}

第三个神奇地命名为ChildChildrenClass的类:

public class ChildChildrenClass
    {
         private EntityRef<ChildClass> _Child;

         [Column]
         public int Id { get; set; }

         [Column]
         public int ChildId { get; set; }

         [Association(Storage = "_Child", IsForeignKey = true, ThisKey = "ChildId", OtherKey = "Id")]
         public ChildClass Child
         {
               get { return _Child.Entity; }
               set { _Child.Entity = value; }
         }
    }

当我们对ChildClass对象进行更新并删除与之关联的一些ChildChildrenClass项时,会出现问题。代码如下所示:

DataContext dc = new DataContext(conStr);
dc.StartTransaction();//our custom method for handling transactions
ChildClass cclass = dc.ChildClass.GetById(id);//our method for getting the ChildClass from db
//... here we set some values we want to edit
//...
//...
dc.SubmitChanges(ConflictMode.FailOnFirstConflict);//these actions are cool
//after this the problems arise
 List<ChildChildrenClass> ccc = GetAllChildren();//method that gets all the childChildrenClass objects from db
foreach (ChildChildrenClass child in ccc)
{
     dc.GetTable(child.GetType()).DeleteOnSubmit(child);
}
dc.SubmitChanges(ConflictMode.FailOnFirstConflict);
//AFTER CALLING THIS METHOD THE PROBLEM APPEARS

上面提到的问题是cclass.Mother属性被神奇地设置为null。 在经过大量调试(在Mother set方法中显示刹车点后发现这一点)后,我们注意到在某些外部代码中SubmitChanges()期间该属性被设置为null。

SubmitChanges()方法成功完成(删除了ChildChildrenClass项)但这会导致在此之后运行的代码出现问题。 我们使用相同的DataContext(因为事务)并再次调用抛出此异常的SubmitChanges()方法:

System.InvalidOperationException:尝试删除MotherClass和ChildClass之间的关系。 但是,其中一个关系的外键(ChildClass.MotherId)不能设置为null。 在System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.SynchDependentData()处于System.Data.Linq.ChangeProcessor.ValidateAll(IEnumerable`1列表)的System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)处于System.Data的System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.SynchDependentData() .Linq.DataContext.SubmitChanges(ConflictMode failureMode)

很久以前,当我写博客引擎时,我也遇到过这个问题。 从连接表中删除了几行后出现了问题。 删除这些东西没关系,那么无论我做了什么,下一个SubmitChanges()出现这个确切的异常。

在花了大约一天左右的时间解决问题后,我重新解决了一个问题:

  • 创建DataContext的新实例
  • 从新的DataContext获取正在使用的任何实体的新实例

我知道这非常 hacky,但这是我解决它的唯一方法。 我看到你在那里使用了一个交易,这会让这更难一点。 也许尝试使用两个不同的事务(一个用于旧的DataContext,一个用于新的),如果第二个失败,则回滚第一个事务?
我知道这很黑。

也许尝试使用另一个没有问题的ORM(例如NHibernate)。

不要使用LinQ-To-SQL,因为

  1. 它已被微软停产
  2. 这是一个很好的工具,但仅限于非常简单的域。 它有关系问题。
  3. 有很多选择。 如果需要Design-Time Support,请选择ADO.NET Entity Framework。 如果你有一个复杂的域来映射尝试NHibernate,它也具有很强的持久性无知。 那里也有很多亚音的粉丝。

永远不应该重用DataContext实例。 每次因为框架无法确保在SubmitChanges()调用之间没有更改数据,建议的方法是在提交更改后处理DataContext并在另一个需要SubmitChanges()事务时创建一个新的DataContext需要打电话。

此外, DataContext对象已经包装了事务中的任何插入,更改和/或删除。

暂无
暂无

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

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