I know this looks a bit long but i tried to explain the problem as throughly as i could.
We are having a very 'exotic' problem with the linq to sql data context class. We have a n-tiered architectured structured like this: 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:
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 that is magically named 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 arises when we do an update on a ChildClass object and delete some of the ChildChildrenClass items that are 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 a lot of debugging (placing brakepoints in the Mother set method revealed this) we noticed that the property is being set to null during SubmitChanges() in some external code.
The SubmitChanges() method completes successfully (the ChildChildrenClass items are deleted) but this causes a problem with the code that runs after this. We are using the same DataContext (because of the transaction) and calling again the SubmitChanges() method that throws this exception:
System.InvalidOperationException: An attempt was made to remove a relationship between a MotherClass and a ChildClass. However, one of the relationship's foreign keys (ChildClass.MotherId) cannot be set to 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)