DbContext查询性能较差与ObjectContext相比

18

我最近将我的实体模型从使用4.1的ObjectContext移植到使用5.0的DbContext。然而,我开始后悔这样做,因为我注意到在使用DbContext时进行查询的性能非常差,相对于使用ObjectContext。以下是测试场景:

两个上下文都使用大约600张表格的同一数据库。它们的LazyLoading和ProxyCreation都已关闭(未在代码示例中显示)。它们都有预生成的视图。

测试首先进行1次调用以加载元数据工作区。然后,在执行100次的for循环中,我新建了一个Context并进行了一个需要前10个结果的调用。(我在for循环内部创建Context,因为这模拟了在WCF服务中使用的情况,每次都会创建Context)

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方法是主要问题所在。该方法在每次查询时都会被调用,似乎是为了检索metadataworkspace并遍历OSpace中的每个项。使用AsNoTracking并不能帮助解决问题。

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

3个回答

4

我也对代码优先方法的表现不佳感到担忧,所以我在类似于你的场景中进行了一些基准测试。

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

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

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

例如,只检索10条记录

enter image description here

请注意,Code First 比 Model First 慢得多,并且跟踪和不跟踪之间没有明显的区别 - 这两个观察结果与您的完全相同。
但是,当检索10000行时,您会遇到:

enter image description here

请注意,在notracking版本中,代码优先和模型优先几乎没有区别。而且,两者的性能都非常出色,几乎与原始ado.net数据读取器一样快。
请查看我的博客文章以获取更多详细信息。
这个简单的基准测试帮助我接受了代码优先的本质。对于较小的项目,我仍然更喜欢它,因为它具有两个特点:poco实体和迁移。另一方面,对于性能要求关键的项目,我永远不会选择其中任何一个。这实际上意味着我可能再也不会使用模型优先方法了。
(顺便说一句:我的基准测试还揭示了nHibernate存在问题。尽管我咨询了两位每天使用NH的独立开发人员,但仍未找到任何人帮助我解释这个问题)

2

DbContext是对ObjectContext的包装器。这里有一个关于你问题的很好的答案。为了更易于使用,可能会牺牲性能。


-3

我使用Simple.Data查询数百万条记录,它的工作效率非常高且速度很快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接