locked
Unable to persist : Multiple added entities may have the same primary key RRS feed

  • Question

  • Hello,

    I have the very classical Order - OderDetail - Product use case.

    I've made my database, my entity framework model and exposed it as a DataServices Read/Write.

    Order, OrderDetail and Product table have a Id column which is a PK based on an IDENTITY column (auto incr)

    From the client, I try the following :

    MyEntities session1 = new MyEntities(svcUri);
    
    Order o = new Order();
    
    session1.AddToOrder(o);
    
    o.OrderDate = DateTime.Now;
    
    
    
    Product p1 = new Product();
    
    session1.AddToProduct(p1);
    
    p1.ProductDescription = "Product1";
    
    
    
    Product p2 = new Product();
    
    session1.AddToProduct(p2);
    
    p2.ProductDescription = "Product2";
    
    
    
    OrderDetails d1 = new OrderDetails() {Product = p1, Amount = 1};
    
    session1.AddToOrderDetails(d1);
    
    o.OrderDetails.Add(d1);
    
    
    
    var response1 = session1.SaveChanges(SaveChangesOptions.Batch);

    I receive the following error :

    Unable to determine the principal end of the 'MyEntities.FK_OrderDetails_Product' relationship. Multiple added entities may have the same primary key.

    I try to initialize every Id (PK)  of every object I create on the client using temporary values (-1,-2,-3,...) and then I got an other error message :

    The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_OrdeDetails_Order\". The conflict occurred in database \"MyEntities\", table \"dbo.Order\", column 'OrderId'.
\nThe statement has been terminated.

    I tried to perform the code directly on the EntityFramework Model (on the server side) and it works. So my EF model seems to be ok.

    It looks like there are some limitations dues to the DataServices Layer...

    Any body from MS can help? Thanks.

    Monday, September 13, 2010 10:12 AM

Answers

All replies

  • There are 2 issues:

    1> Issue one is about primary keys - the one that you were able to workaround using temporary values. Not sure why this is happening. Since you haven't initialized the key in the client, they must send the default values to the server. If the EF knows that the keys are server generated, this should work. Did you set the server generated attribute in the csdl?

    2> The second issue is about the Foreign key constraint. The issue is when you are inserting a new OrderDetails, you need to set the Order and Product at the same time. You need to explicitly call context API when you trying to set up relationship - setting the property values directly does not help, unless you are using DataServiceCollection to track changes automatically for you.

    OrderDetails d1 = new OrderDetails() {Product = p1, Amount = 1};
    session1.AddToOrderDetails(d1);
    o.OrderDetails.Add(d1);
    session1.SetLink(d1, "Product", p1);
    session1.AddLink(o, "OrderDetails", d1);

    The last 2 lines tells the context about the relationship changes and sends the right request to the server.

    Hope this helps.

    Thanks

    Pratik


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Tuesday, September 14, 2010 6:59 PM
    Moderator
  • Thank you Pratik for your answer.

    1> Yes Ids are generated by the server and I have StoreGeneratedPattern="Identity" in my EF model.

    2> I've added the 2 lines (SetLink and AddLink) and now it works. Thanks !

    I don't understand why we have to call SetLink or AddLink because It seems redundant with :

    OrderDetails d1 = new OrderDetails() { Product = p1};

     and

    o.OrderDetails.Add(d1);

    In the same idea, why do I I have to call

    session1.AddToOrderDetails(d1);

    if I've already done "o.OrderDetails.Add(d1);" and o is an order already added to the session1.

    If you compare with RIA Services, you don't have to call such redundant APIs. Could you explain me we why ?

    session1.AddToOrderDetails(d1);

    Thanks.

    Wednesday, September 15, 2010 7:35 AM
  • I just replied in another thread: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/c8e0feb7-9b33-450c-ad99-eb1122f89eae

    You do not have to call SetLink/AddLink method if you use DataServiceCollection and have the objects tracked.

    Hope this helps.

    Thanks

    Pratik


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, September 22, 2010 4:55 PM
    Moderator
  • Hi,

     

    I am writing to check the status of the issue on your side.  Would you mind letting us know the result of the suggestions? 

     

    If you need further assistance, please feel free to let me know.   I will be more than happy to be of assistance.

     

    Have a nice day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, September 29, 2010 2:08 AM
    Moderator