我知道这看起来有点冗长,但我尽可能详细地解释了问题。
我们在使用linq to sql数据上下文类时遇到了一个非常“奇特”的问题。我们有一个三层架构结构,如下所示:我们有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。 at System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.SynchDependentData() at System.Data.Linq.ChangeProcessor.ValidateAll(IEnumerable`1 list) at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)