Reputation: 52745
I have an entity Foo
with a Bars
collection.
This collection is quite big (say, 20,000 elements, and yes, it needs to be loaded entirely, because it's displayed in a TreeView), and the elements are generated automatically based on some parameters of the Foo
that the user can change, using a WPF MVVM application (all processing occurs in the client)
After he is satisfied with the results, he hits save, and DbContext.SaveChanges()
is called.
Generating Bars
implies clearing the collection, then doing a bunch of calculations and adding the new elements. When this is a new, non-persistent Foo
, it's no problem because I can just call foo.Bars.Clear()
The problem is, doing that with already persistent entities causes EF to set bar.Foo = null
in all the elements, instead of deleting them.
My workaround goes like this:
void Regenerate()
{
if (fooIsPersistent)
{
foreach (var bar in foo.Bars.ToList())
context.Entry(bar).State = EntityState.Detached;
deleteOnSave = true;
}
else
foo.Bars.Clear();
AddTheNewCalculatedElements()
}
void Save()
{
if (deleteOnSave)
context.Database.ExecuteSqlCommand("delete Bar where Foo = @Id", param);
context.SaveChanges();
}
The problem with this solution is that it doesn't scale. Calling Entry(bar).State = EntityState.Detached
when there are many entities loaded is even slower than just calling context.Set<Bar>().Remove(bar)
and letting EF do the deletes one by one, so it defeats the purpose of the workaround.
So, my question is: Is there any efficient way to make EF believe the collection is actually empty?
Or should I do it in a completely different way?
Upvotes: 1
Views: 141
Reputation: 52745
Well, it was easier than I thought.
I replaced this line:
context.Entry(bar).State = EntityState.Detached;
with this one (which I thought was more or less equivalent):
((IObjectContextAdapter)context).ObjectContext.Detach(bar);
And it now completes in a reasonable time.
Upvotes: 1