Search code examples
c#winformsentity-frameworklistdynamic-proxy

c# entity framework changing the contents of my lists


I'm getting a really strange glitch and I believe entity framework is to blame. Here's the basic scenario thats going on. I have an entity object, Foo, with a navigation property collection, Bar. Foo in this context is being tracked by entity frameworks change tracking. I run the following code, but the result is very strange

var NewBars = CreateBars(); //CreateBars returns a List<Bars> with two items

//After this code is ran, Foo.Bars AND NewBars will both be lists with 4 items.
//I think its because Foo.Bars has dynamic proxies, entity framework edits bars
//To re-insert the overwritten proxies. 
Foo.Bars = NewBars;

If I put a breakpoint at the var NewBars = CreateBars() line, and step through it piece by piece, everything will come out as expected. Foo.Bars will be a two item list, NewBars will be a two item list. But If I run execution with no breakpoints, or if I break point after I set Foo.Bars = NewBars, then both of these lists miraculously change to 4 item lists. Its weird to me that even the right hand value list is being changed.

At one point, even when I had the execution stopped at a breakpoint, I checked the contents of newbars and it was 2 the first time I looked, and then 4 the next time I looked. It changed while the program was at a halt, so I know theres something going on behind the scenes.

The problem is that because it keeps reinserting the proxies, Im getting primary key conflicts. If the proxies don't re-insert, then everything is fine. Im just wondering, how do I remedy this problem? I just simply want to set Foo.Bars to a new list of items. Any direction on this issue would be greatly appreciated! Thanks!


Solution

  • What do you want to happen to the Bars that are in Foo.Bars before you assign newBars?

    You need to deal with them in some way. They are represeted by rows in a Bar table in your database, right?

    You could remove these old Bars entirely with something like:

    dbContext.Bars.RemoveRange(Foo.Bars);
    dbContext.SaveChages();
    

    then assign your new bars:

    Foo.Bars = NewBars;
    dbContext.SaveChanges();
    

    Alternatively if you still want the old Bars to exist in the db but just not be linked to Foo then you can do:

    Foo.Bars=null;
    Foo.Bars = newBars;
    dbContext.SaveChanges();
    

    (Of course this assumes your db schema allows this without violating any constraints)