我最近将我的实体模型从使用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则不会。我猜测(没有尝试过)具有较少表格的模型,性能差异较小。
答案 0 :(得分:4)
我一直担心代码第一种方法的性能不佳,我在类似于你的方案中执行了一些基准测试
http://netpl.blogspot.com/2013/05/yet-another-orm-micro-benchmark-part-23_15.html
结果并不令人惊讶,因为DbContext是ObjectContext的包装器,为了简单起见,它必须牺牲性能。但是,我的测试表明:
例如,只检索10条记录
请注意,代码优先明显慢于模型,并且跟踪和无跟踪之间没有明显差异 - 两个观察都与您的完全一样。
但是,在检索10000行时,您有
请注意,在notracking版本中,代码优先和模型优先几乎没有区别。此外,两者的表现都非常出色,几乎与原始ado.net datareader一样快。
请关注我的博客文章了解更多详情。
这个简单的基准测试帮助我首先接受了代码的本质。由于两个特性:poco实体和迁移,我仍然更喜欢它用于较小的项目。另一方面,对于性能是关键要求的项目,我绝不会选择其中任何一个。这实际上意味着我可能永远不会再次使用模型第一种方法。
(旁注:我的基准测试也显示nHibernate有问题。即使我已经咨询了两位每天使用NH的独立开发人员,我仍然没有找到任何人来帮助我解释这个问题。
答案 1 :(得分:2)
DbContext是ObjectContext的包装器。关于你的问题,这里很好answer。有可能使它更容易使用,牺牲性能。
答案 2 :(得分:-3)
我使用Simple.Data来查询数百万条记录,而且效果非常好。