many to many relationships : problem with creating a new relation between two new objects in a same disconnected session

Aug 18, 2008 at 4:41 PM
Hi Matt,

I am playing with your wonderful Entitybase class and I like it.
I have modified your demonstration  attaching a new Product at the new Order_Detail you create instead of an existing one in the database :
/*debpa
order_DetailAdded.Product = products.FirstOrDefault();
finpa */

/*debpa*/

Product tempProduct = products.FirstOrDefault();
Product myProduct = new Product();
myProduct.CategoryID = tempProduct.CategoryID;
myProduct.SupplierID = tempProduct.SupplierID;
myProduct.UnitPrice = 1000;
products.Add(myProduct);
order_DetailAdded.Product = myProduct;
// order_DetailAdded.Product = tempProduct;
/*finpa*/
orderAdded.Order_Details.Add(order_DetailAdded);

This give me an error.

I tried a similar scenario in my own environment and it seems this is because linq to sql try to insert the OrderDetail row  in the database before creating the TWO related objects (the OrderAdded AND the myProduct) .

It gives a message like this :
"
Exception The INSERT statement conflicted with the FOREIGN KEY constraint "FK_PersonDebt_Debt". The conflict occurred in database "EVALORM", table "dbo.Debt", column 'Debt_ID'
"
(The Person row corresponding to the PersonDebt relation is inserted first but the Debt row is not  => the PersonDebt row insertion fails).

Am I making a mistake or this is a known issue. It seems to work in a connected mode.

Thanks,
Pat

Aug 21, 2008 at 8:13 AM
Hi Matt,

I further investigated and it seems the problem is due to the use of the CopyEntityDeep function to simulate exchanges of my entity between layers.


My scenario is as follow :
1) I retrieve a loan (without children) from the database
2) I make a copy loanBis of the entity using CopyEntityDeep and call loanBis.SetAsChangeTrackingRoot(true)
3) In my loanBis entity, I create a new person, a new debt and a relation between them
4) I call CopyEntityDeep on LoanBis creating LoanBisBis

Here are the entitytrees corresponding :

------LoanBis entitytree after modifications
-----------------------------------------
Nbr d'éléments liste originale : 5
Nbr d'éléments liste apres filtre distinct : 4
ef69543c-ad5a-4ddd-b5e0-75f2a7339c03 Type : Loan EntityState : Modified, NbForeigKeys : 0
cfe21cae-d844-4b7e-afa0-d97983ff73a0 Type : Person EntityState : New, NbForeigKeys : 1
     Loan : ef69543c-ad5a-4ddd-b5e0-75f2a7339c03
e1d80f8d-e2cc-40e8-9e8a-9ec78277c91b Type : PersonDebt EntityState : New, NbForeigKeys : 2
     Debt : 81e74f4c-f4d0-41ea-a082-0914463a3bd0
     Person : cfe21cae-d844-4b7e-afa0-d97983ff73a0
81e74f4c-f4d0-41ea-a082-0914463a3bd0 Type : Debt EntityState : New, NbForeigKeys : 1
     Loan : ef69543c-ad5a-4ddd-b5e0-75f2a7339c03
e1d80f8d-e2cc-40e8-9e8a-9ec78277c91b Type : PersonDebt EntityState : New, NbForeigKeys : 2
     Debt : 81e74f4c-f4d0-41ea-a082-0914463a3bd0
     Person : cfe21cae-d844-4b7e-afa0-d97983ff73a0
------LoanBisBis After CopyEntityDeep
-----------------------------------------
Nbr d'éléments liste originale : 5
Nbr d'éléments liste apres filtre distinct : 5
ef69543c-ad5a-4ddd-b5e0-75f2a7339c03 Type : Loan EntityState : Modified, NbForeigKeys : 0
cfe21cae-d844-4b7e-afa0-d97983ff73a0 Type : Person EntityState : New, NbForeigKeys : 1
     Loan : ef69543c-ad5a-4ddd-b5e0-75f2a7339c03
e1d80f8d-e2cc-40e8-9e8a-9ec78277c91b Type : PersonDebt EntityState : New, NbForeigKeys : 2
     Debt = null
     Person : cfe21cae-d844-4b7e-afa0-d97983ff73a0
81e74f4c-f4d0-41ea-a082-0914463a3bd0 Type : Debt EntityState : New, NbForeigKeys : 1
     Loan : ef69543c-ad5a-4ddd-b5e0-75f2a7339c03
e1d80f8d-e2cc-40e8-9e8a-9ec78277c91b Type : PersonDebt EntityState : New, NbForeigKeys : 2
     Debt : 81e74f4c-f4d0-41ea-a082-0914463a3bd0
     Person = null
-----------------------------------------

As serialization is made in unidirectional mode, LoanBisBis has two different childs, one for person and another for Debt. This is problem  when we update the database. So, I have to correct the LoanBisBis graph

------After graphe consistency correction
-----------------------------------------
AFFICHAGE DE L'ARBRE
Nbr d'éléments liste originale : 5
Nbr d'éléments liste apres filtre distinct : 4
ef69543c-ad5a-4ddd-b5e0-75f2a7339c03 Type : Loan EntityState : Modified, NbForeigKeys : 0
cfe21cae-d844-4b7e-afa0-d97983ff73a0 Type : Person EntityState : New, NbForeigKeys : 1
     Loan : ef69543c-ad5a-4ddd-b5e0-75f2a7339c03
e1d80f8d-e2cc-40e8-9e8a-9ec78277c91b Type : PersonDebt EntityState : New, NbForeigKeys : 2
     Debt : 81e74f4c-f4d0-41ea-a082-0914463a3bd0
     Person : cfe21cae-d844-4b7e-afa0-d97983ff73a0
81e74f4c-f4d0-41ea-a082-0914463a3bd0 Type : Debt EntityState : New, NbForeigKeys : 1
     Loan : ef69543c-ad5a-4ddd-b5e0-75f2a7339c03
e1d80f8d-e2cc-40e8-9e8a-9ec78277c91b Type : PersonDebt EntityState : New, NbForeigKeys : 2
     Debt : 81e74f4c-f4d0-41ea-a082-0914463a3bd0
     Person : cfe21cae-d844-4b7e-afa0-d97983ff73a0


And it works perfectly,

Thanks,

Patrick
Aug 25, 2008 at 12:57 PM
Edited Aug 25, 2008 at 12:57 PM
Hi Patrick,

Sorry for the late reply.

I'll try and answer your post, however I don't understand what the problem is exactly, but it seems like you have having problems with the direction of your relationships and unidirectional serialization.

Fundamentally, with serialization it's all about relationships, it basically breaks down into parent and child relationships (Parent-->Child).  When a parent is saved, it's children are also inserted or update (if necessary).

When looking at the example that's shipped with my code, if you have a look at the DBML you'll file this:

Customer-->Order-->Order_Detail<--Product

In this case, if a new product is added or updated in the graph, when serialized (or deep copied), being unidirectional only following is serialized:

Customer-->Order-->Order_Detail

Product is not serialized at all, however Order_Detail will contain the correct FK values to the related product (more like a reference)

In this case, if you wanted the product to be applied to the database, you'd have to sync the new product with the database first (treated like it's own entity graph) and then add the rest of tree.

By the looks of your last post, it looks like you've discovered the this anyway? If not could you describe the DBML you are using for me?



Aug 26, 2008 at 4:44 PM
Hi Matt,

Thank you for you reply and all your work on the entitybase. We are planning to use it for our project.

Actually, the problem encountered with my modifications in the LINQEntityBaseExample project using the  Customer-->Order-->Order_Detail<--Product DBML is slightly different from this I encountered in my project with this DBML :

               ---->Person--------->| 
loan-----|                                    |PersonDebt   
              ---->Debt------------>|


Creating a new Person, a new Debt and a new relation PersonDebt  beetwen them, after a deepcopy, I get two PersonDebt relations, each one having only one related parent. So, I made a function to correct the graph consistency after serialization. I will give you a sample of this function if you want.

Thank you for your explanation on the first problem.

I am working on another scenario I will post about it soon I think.

Best regards,

Patrick