Search code examples
c#.netentity-frameworkwcfodata

saving new entity to DataServiceContext with linked new entities


I have a service reference to a DataServiceContext class in my client project.

I need to create a new entity and save it to database context.

Everything goes well while I save this entity alone, without any linked entities.

A a = new A();
context.AddToAs(a);
context.BeginSaveChanges(o=>{
    //some after-save code there
}, null);

However, the code like this:

A a = new a(); //parent entity
B b = new b(); //child entity which has corresponding b.A navigation
               //property and b.AId field for referencing 'A' entity primary
               //key.
a.b = b;
context.AddToAs(a);
context.AddToBs(b);
context.SetLink(b, "A", a);
context.BeginSaveChanges(o=>{
    //some after-save code here
}, null);

...fails with "The INSERT statement conflicted with the FOREIGN KEY constraint" error.

Of course I understand that newly created 'A' entity has its primary key set to '0', and corresponding navigation properties in 'B' entity, like b.AId are equal to '0' upon saving as well. And that does cause problem - 'A' entity with '0' primary key already exists in database.

So I have to save 'A' entity first, without any linked 'B's assigned, so that 'A' entity is saved and receiving real ID, and then - attach 'B's to A and save context once more, so that 'B' entities are saved.

I am more than sure that I am doing something terribly wrong there, can anybody give any suggestion on how to make it with a single SaveChanges?


Solution

  • I encountered the same problem. My solution was to not link the objects in memory. I only used context.SetLink. So for your example I think this would work:

    A a = new a(); //parent entity
    B b = new b(); //child entity which has corresponding b.A navigation
                   //property and b.AId field for referencing 'A' entity primary
                   //key.
    // Omit this line. a.b = b;
    context.AddToAs(a);
    context.AddToBs(b);
    context.SetLink(b, "A", a);
    context.BeginSaveChanges(o=>{
        //some after-save code here
    }, null);
    

    In my situation the created objects were not used after the save changes call, so it did not matter that the objects were not linked in memory after the save call. If you need the objects to also be linked in memory after the save call, I can think of two things to try:

    • Load the objects from the context after saving them. It is a bit of an unnecessary database call, but it means the loaded objects will have the correct linking.
    • Manually assign the associations (e.g. a.b = b;) after saving your changes.