18

我最近将我的实体模型从使用 4.1 的 ObjectContext 移动到使用 5.0 的 DbContext。我开始后悔这样做,因为我注意到使用 DbContext 与 ObjectContext 的查询性能很差。这是测试场景:

两种上下文都使用具有大约 600 个表的相同数据库。两者都关闭了 LazyLoading 和 ProxyCreation(代码示例中未显示)。两者都有预先生成的视图。

测试首先进行 1 次调用以加载元数据工作区。然后在一个执行 100 次的 for 循环中,我新建一个上下文并进行一次调用,该调用采用前 10 次。(我在 for 循环内创建上下文,因为这模拟了在 WCF 服务中使用,这将创建每次的上下文)

for (int i = 0; i < 100; i++)
{
    using (MyEntities db = new MyEntities())
    {
        var a = db.MyObject.Take(10).ToList();
    } 
} 

当我使用 ObjectContext 运行它时,大约需要 4.5 秒。当我使用 DbContext 运行它时,大约需要 17 秒。我使用 RedGate 的性能分析器对此进行了分析。对于 DbContext,罪魁祸首似乎是一个名为 UpdateEntitySetMappings 的方法。这在每个查询中都会调用,并且似乎检索元数据工作空间并循环遍历 OSpace 中的每个项目。AsNoTracking 没有帮助。

编辑:为了提供更好的细节,问题与 DbSet 与 ObjectSet 的创建\初始化有关,而不是实际查询。当我使用 ObjectContext 进行调用时,创建 ObjectSet 平均需要 42 毫秒。当我使用 DbContext 进行调用时,创建内部数据库集大约需要 140 毫秒。ObjectSet 和 DbSet 都从元数据工作区进行一些实体集映射查找。我注意到的是,DbSet 为工作区中的所有类型执行此操作,而 ObjectSet 没有。我猜(还没有尝试过)具有较少表的模型的性能差异较小。

4

3 回答 3

4

我也一直担心代码优先方法的性能不佳,并且我在与您类似的场景中执行了一些基准测试

http://netpl.blogspot.com/2013/05/yet-another-orm-micro-benchmark-part-23_15.html

结果并不令人惊讶,因为 DbContext 是 ObjectContext 的包装器,它必须为了简单而牺牲性能。但是,我的测试表明:

  • 您检索的记录越多,差异就越小
  • 您检索的记录越多,如果您想更快,关闭跟踪就越重要

例如,仅检索 10 条记录

在此处输入图像描述

请注意,代码优先比模型优先慢得多,并且跟踪和不跟踪之间没有明显的区别 - 两种观察结果都与您的完全一样。

但是,在检索 10000 行时,您有

在此处输入图像描述

请注意,在 nottracking 版本中,代码优先和模型优先几乎没有区别。此外,两者的性能都出奇的好,几乎与原始的 ado.net 数据读取器一样快。

请关注我的博客条目以获取更多详细信息。

这个简单的基准帮助我首先接受了代码的本质。由于两个功能,我仍然更喜欢它用于较小的项目:poco 实体和迁移。另一方面,对于性能是关键要求的项目,我永远不会选择两者中的任何一个。这实际上意味着我可能永远不会再使用模型优先的方法了。

(附注:我的基准测试还显示 nHibernate 存在问题。尽管我咨询了两个每天使用 NH 的独立开发人员,但我仍然没有找到任何人来帮助我解释这一点)

于 2013-10-01T20:06:37.130 回答
2

DbContext 是 ObjectContext 的包装器。这是关于您的问题的好答案。有可能是为了更容易使用,他们牺牲了性能。

于 2013-03-26T12:11:23.290 回答
-3

我使用Simple.Data来查询数百万条记录,它运行得非常好和快。

于 2013-04-01T19:31:17.577 回答