我最近将我的实体模型从使用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则不会。我猜测(没有尝试过),在表较少的模型中,性能差异会更小。