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
精彩评论