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

Atz*_*oya 6 .net c# datacontext linq-to-sql

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

我们对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; }
     }
}
Run Code Online (Sandbox Code Playgroud)

而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; }
     }
}
Run Code Online (Sandbox Code Playgroud)

第三个神奇地命名为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; }
         }
    }
Run Code Online (Sandbox Code Playgroud)

当我们对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
Run Code Online (Sandbox Code Playgroud)

上面提到的问题是cclass.Mother属性被神奇地设置为null.大量的调试后(将在母亲brakepoints设置方法揭示这一点),我们注意到的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 .Linq.DataContext.SubmitChanges(ConflictMode failureMode)

Ven*_*emo 2

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

在花了大约一天左右的时间解决问题后,我恢复了解决方法:

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

我知道这棘手,但这是我解决它的唯一方法。我看到你在那里使用交易,这会让事情变得有点困难。也许尝试使用两个不同的事务(一个用于旧的 DataContext,一个用于新的),并在第二个失败时回滚第一个事务?
我知道这很糟糕。

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