开发者

Entity Framework incorrectly saving an entity when I never added it to the Context

I'm using Entity Framework in开发者_如何学编程 .NET 4.0. I have a Subscription entity, which has many CFile entities. I create a new CFile entity, but never actually call AddObject on it. Later on I try to save the Subscription entity that is related to it and EF tries to save the CFile instance, which I never intended!

Simplified code:

var subscription = new Subscription();
Context.Subscription.AddObject(subscription);
Context.SaveChanges();

var cfile = new CFile() { Subscription = subscription };
if (SomeChecksPass(cfile))
{
    Context.CFiles.AddObject(cfile);
}
else
{
    // No AddObject!
}

subscription.SomeProperty = "changed";
Context.SaveChanges(); // Saves cfile as well, even if I don't want to!

I understand why it's happening, but how do I get it to not do this? This creates a rather subtle and obscure bug (the real code is obviously much more complex). I want it to only save entities that I explicitly passed to AddObject.

I also know of a workaround: call Detach on the entity that I don't want saved. It's not a good workaround, however, because I have to make sure I call Detach in every possible code path where cfile is not saved (and in some code paths it is saved), so it has to be called after that decision is made, but before anything else is saved. This is very brittle and I really don't want to rely on it.

Edit: cfile is created because I do want to save it most of the time, but if some validation fails or some error occurs then I don't. I still want to save some changes to the subscription object, though.


Try exposing the foreign key in your EDMX (if not already there) and do something like this instead:-

var cfile = new CFile() { SubscriptionId = subscription.Id };

That should be enough to prevent the object graph from forming.

You might need to call Refresh on the subscription object after creating it (depends on how your IDs are being generated - most will get updated automatically when you SaveChanges()).


You do not directly control what entities to save in Entity Framework, it saves what it thinks it should, it works with associated Object Graphs. You can put some logic in ObjectContext.SaveChanges override using ObjectStateManager but this is pretty ugly.

If you need more control on what to save and when, maybe it is better to use some other pattern like Repository | ActiveRecord where you have better control on separate entities. Or you will often find yourself in situations you described.


I had the same problem when using:

List<Ey> eys = dc.Context.Ey.ToList();
eys = eys .Where(h => h.Employee == myEmployee).ToList();
Ey esh;
for (int k = 1; k < 5; k++)
{
EmployeeSkillHistory duplicate = histories.Where(h => h.Sl == esh.Sl).FirstOrDefault();
   if (duplicate == null)
      { dc.Context.Ey.AddObject(esh); } else { dc.Context.Ey.DeleteObject(esh); }
dc.Context.SaveChanges();
}

Before using

else { dc.Context.Ey.DeleteObject(esh); }

Duplicates were saved in my database

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜