为什么Entity Framework中的这些Add / .Modify操作如此之慢?

时间:2015-07-24 16:21:54

标签: c# entity-framework wcf

在一些用户抱怨速度缓慢之后,我一直在寻找一个在WCF应用程序中查看性能瓶颈的分析器。

令我惊讶的是,几乎所有问题都归结为实体框架操作。我们使用存储库模式和大多数&​​#34;添加/修改"代码看起来非常像这样:

public void Thing_Add(Thing thing)
{
    Log.Trace("Thing_Add called with ThingID " + thing.ThingID);

    if (db.Things.Any(m => m.ThingID == thing.ThingID))
    {
        db.Entry(thing).State = System.Data.EntityState.Modified;
    }
    else
    {
        db.Things.Add(thing);
    }
}

这显然是将添加/更新检查包装到单个函数中的便捷方式。

现在,我知道在进行插入和更新时,EF并不是最有效的方法。但是,我的理解是(有一点研究证明)它应该能够比用户可能注意到的更快地处理几百条记录。

但这会导致小小的upserts出现大瓶颈。例如,在一种情况下,处理大约50个记录需要6秒。这是一个特别糟糕的例子,但在这个应用程序中似乎存在小型EF upserts花费一两秒钟的实例。当然足以惹恼用户。

我们正在使用Entity Framework 5和Database First模型。分析器说,导致问题的不是Log.Trace。可能导致这种情况的原因,我该如何调查并解决问题?

1 个答案:

答案 0 :(得分:1)

我在另一个SO帖子上找到问题的根源:DbContext is very slow when adding and deleting

事实证明,当你处理大量物体时,特别是在循环中,变化跟踪的逐渐积累会使EF变得越来越慢。

在这种情况下刷新DbContext是不够的,因为我们仍在使用太多链接的实体。所以我把它放在存储库中:

public void AutoDetectChangesEnabled(bool detectChanges)
{
    db.Configuration.AutoDetectChangesEnabled = detectChanges;
}

现在可以使用它在循环插入之前打开和关闭AutoDetectChangesEnabled:

try
{
    rep.AutoDetectChangesEnabled(false);
    foreach (var thing in thingsInFile)
    {
        rep.Thing_add(new Thing(thing));
    }
}
finally
{
    rep.AutoDetectChangesEnabled(true);
}

这让人有所不同。虽然它需要小心使用,因为它会阻止EF识别对已更改对象的潜在更新。