DbContext查询性能差与ObjectContext相比

时间:2013-03-23 17:00:50

标签: c# .net entity-framework

我最近将我的实体模型从使用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的方法。这是在每个查询上调用的,并且似乎检索元数据工作空间并循环遍历OS空间中的每个项目。 AsNoTracking没有帮助。

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

3 个答案:

答案 0 :(得分:4)

我一直担心代码第一种方法的性能不佳,我在类似于你的方案中执行了一些基准测试

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

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

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

例如,只检索10条记录

enter image description here

请注意,代码优先明显慢于模型,并且跟踪和无跟踪之间没有明显差异 - 两个观察都与您的完全一样。

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

enter image description here

请注意,在notracking版本中,代码优先和模型优先几乎没有区别。此外,两者的表现都非常出色,几乎与原始ado.net datareader一样快。

请关注我的博客文章了解更多详情。

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

(旁注:我的基准测试也显示nHibernate有问题。即使我已经咨询了两位每天使用NH的独立开发人员,我仍然没有找到任何人来帮助我解释这个问题。

答案 1 :(得分:2)

DbContext是ObjectContext的包装器。关于你的问题,这里很好answer。有可能使它更容易使用,牺牲性能。

答案 2 :(得分:-3)

我使用Simple.Data来查询数百万条记录,而且效果非常好。