Я знаю, это выглядит немного длинно, но я пытался объяснить проблему как можно более подробно.
У нас очень экзотическая проблема с классом контекста данных 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. После большой отладки (размещение точек торможения в методе «Мать» показало это), мы заметили, что во время SubmitChanges () в некотором внешнем коде для свойства устанавливается ноль.
Метод SubmitChanges () завершается успешно (элементы ChildChildrenClass удаляются), но это вызывает проблему с кодом, который выполняется после этого. Мы используем тот же DataContext (из-за транзакции) и снова вызываем метод SubmitChanges (), который выдает это исключение:
System.InvalidOperationException: была предпринята попытка удалить связь между MotherClass и ChildClass. Однако один из внешних ключей отношения (ChildClass.MotherId) не может быть установлен в нуль.
в System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.SynchDependentData ()
в System.Data.Linq.ChangeProcessor.ValidateAll (список IEnumerable`1)
в System.Data.Linq.ChangeProcessor.SubmitChanges (ConflictMode faultMode)
в System.Data.Linq.DataContext.SubmitChanges (ConflictMode faultMode)