如何快速清除大型持久性集合?

时间:2011-10-27 20:40:13

标签: entity-framework-4.1

我有一个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相信该集合实际上是空的?

还是应该以完全不同的方式进行?

1 个答案:

答案 0 :(得分:1)

嗯,这比我想象的容易。

我替换了这一行:

context.Entry(bar).State = EntityState.Detached;

这个(我认为或多或少相当):

((IObjectContextAdapter)context).ObjectContext.Detach(bar);

它现在在合理的时间内完成。