I know this looks a little long, but I tried to explain the problem as much as I could.
We are having a very "exotic" problem with the linq to sql data context class. We have an n-tier architecture, structured as follows: we have 3 classes MotherClass, ChildClass, ChildChildrenClass
MotherClass looks something like this:
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; } } }
And ChildClass looks something like this:
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; } } }
And the third class, magically called 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; } } }
The problem occurs when updating the ChildClass object and deleting some of the ChildChildrenClass elements associated with it. The code looks something like this:
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
The problem mentioned above is that the cclass.Mother property is magically set to null. After much debugging (placing bracepoints in the Mother set method revealed this), we noticed that the property is null during SubmitChanges () in some external code.
The SubmitChanges () method completed successfully (ChildChildrenClass elements removed), but this causes a problem with the code that runs after that. We use the same DataContext (due to the transaction) and call the SubmitChanges () method again, which throws this exception:
System.InvalidOperationException: An attempt was made to remove the relationship between MotherClass and ChildClass. However, one of the foreign relationship keys (ChildClass.MotherId) cannot be null. in System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.SynchDependentData () in System.Data.Linq.ChangeProcessor.ValidateAll (IEnumerable`1 list) in System.Data.Linq.ChangeProcessor.Submittode.DataModeMangata.DataModemata .Linq.DataContext.SubmitChanges (ConflictMode failureMode)