我有一个Foo
个实体Bars
。
这个集合非常大(比如,20,000个元素,是的,它需要完全加载,因为它显示在TreeView中),并且元素是根据Foo
的一些参数自动生成的。用户可以使用WPF MVVM应用程序进行更改(所有处理都在客户端进行)
在对结果感到满意后,他点击了保存,并且DbContext.SaveChanges()
被调用。
生成Bars
意味着清除集合,然后进行一系列计算并添加新元素。当这是一个新的非持久性Foo
时,没问题,因为我可以调用foo.Bars.Clear()
问题是,对已经存在的实体执行此操作会导致EF在所有元素中设置bar.Foo = null
,而不是删除它们。
我的解决方法是这样的:
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();
}
此解决方案的问题在于它无法扩展。当加载了许多实体时调用Entry(bar).State = EntityState.Detached
甚至比调用context.Set<Bar>().Remove(bar)
并让EF逐个删除更慢,因此它违背了解决方法的目的。
所以,我的问题是:是否有任何有效的方法让EF相信该集合实际上是空的?
还是应该以完全不同的方式进行?
答案 0 :(得分:1)
嗯,这比我想象的容易。
我替换了这一行:
context.Entry(bar).State = EntityState.Detached;
这个(我认为或多或少相当):
((IObjectContextAdapter)context).ObjectContext.Detach(bar);
它现在在合理的时间内完成。