EF 4.3.1和EF 5.0 DbSet.Local比实际的数据库查询慢

MCa*_*tle 20 .net vb.net entity-framework entity-framework-5 entity-framework-4.3.1

我有一个包含大约16,500个城市的表的数据库,以及该数据库的EF数据模型(数据库优先).我用代码将它们预加载到内存中:

Db.Cities.Load()
Run Code Online (Sandbox Code Playgroud)

...然后在使用它们的时候,我尝试了以下每个查询:

Dim cities() As String = Db.Cities.Select(Function(c) c.CityName).ToArray

Dim cities() As String = Db.Cities.Local.Select(Function(c) c.CityName).ToArray
Run Code Online (Sandbox Code Playgroud)

第一个查询是快速的(约10毫秒),但是第二个查询第一次运行大约需要2.3秒(尽管它比第一个查询在此之后调用时更快).

这没有意义,因为SQL Server Profiler验证第一个查询是在另一台机器上命中数据库,但第二个查询不是!

我试过关掉Db.Configuration.AutoDetectChangesEnabled,我试过预先生成视图.

我能做些什么来.Local加快速度?(并非所有运行此应用程序的客户端都将位于快速LAN上.)

N J*_*nes 9

Local使用Resharper的便利功能走完了物业的源头.DetectChanges如果你正在运行的是以上三行,你首先会看到一个可能不是你问题的电话.但是,然后EF为Local项目创建一个新的ObservableCollection 并逐项填充.在第一次通话中,其中任何一个都是昂贵的.

直接针对DbSetwill 的查询路由到EF数据库提供程序,我确定直接访问内部本地缓存.


MCa*_*tle 6

以下扩展方法将返回IEnumerable<T>包含DbSet的本地缓存实体的内容,而不会DbSet.Local()检测上下文更改和创建ObservableCollection<T>对象的方法所产生的启动开销.

<Extension()>
Public Function QuickLocal(Of T As Class)(ByRef DbCollection As DbSet(Of T)) As IEnumerable(Of T)
    Dim baseType = DbCollection.[GetType]().GetGenericArguments(0)
    Dim internalSet = DbCollection.GetType().GetField("_internalSet", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance).GetValue(DbCollection)
    Dim internalContext = internalSet.GetType().GetProperty("InternalContext").GetValue(internalSet, Nothing)
    Return DirectCast(internalContext.GetType.GetMethod("GetLocalEntities").MakeGenericMethod(baseType).Invoke(internalContext, Nothing), IEnumerable(Of T))
End Function
Run Code Online (Sandbox Code Playgroud)

调用.QuickLocal包含19,679个实体的DbSet需要9 ms,而.Local在第一次调用时调用需要2121 ms.

  • 啊,如果这是问题,你可以避免反射并直接访问`ObjectStateManager`:`((IObjectContextAdapter)dbContext).ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged | EntityState.Added | EntityState.Modified).Select(entry = > entry.Entity).OfType <T>()` (4认同)

Aka*_*ava 0

为什么不简单地保存第一个查询中的字符串列表并使用它呢。

List<string> cities = db.Cities.Select( x=>x.CityName).ToList();
Run Code Online (Sandbox Code Playgroud)

由于 Select 可能会进行一些一致性检查,本地可能会更慢。