为什么这些添加/.修改实体框架的操作太慢

本文关键字:框架 操作 实体 修改 添加 为什么 | 更新日期: 2023-09-27 18:04:26

在一些用户抱怨WCF应用程序运行缓慢后,我一直在使用一个性能分析器来查看性能瓶颈。

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

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在进行插入和更新时不是最有效的。然而,我的理解是(一点研究证实了这一点),它应该能够比用户可能注意到的更快地处理几百条记录。

但是这对小的upts造成了很大的瓶颈。例如,在一个案例中,处理大约50条记录需要6秒。这是一个特别糟糕的例子,但似乎在这个应用程序中到处都有这样的例子,小的EF反转需要一两秒钟以上的时间。当然足以惹恼用户。

我们使用实体框架5与数据库第一模型。侧写师说那不是日志。跟踪导致问题的原因。可能导致这种情况的原因是什么?我该如何调查和解决这个问题?

为什么这些添加/.修改实体框架的操作太慢

我在另一个SO帖子上发现了问题的根源:添加和删除

时DbContext非常慢

事实证明,当您处理大量对象时,特别是在循环中,变化跟踪的逐渐积累使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识别对已更改对象的潜在更新。