我有与16,500个城市的表,该数据库的EF数据模型(数据库优先)的数据库。 我预装他们与代码存储器:
Db.Cities.Load()
......那么当它的时间使用它们,我已经试过每个以下查询:
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
第一个查询速度快(〜10毫秒),但第二个需要约2.3秒,第一次运行时(尽管这比当它后称为第一查询更快)。
这是没有意义的,因为SQL Server事件探查器验证第一查询击中另一台机器上的数据库,但第二个不是!
我试过关掉Db.Configuration.AutoDetectChangesEnabled
,我尝试了预先生成的意见。
我能做些什么使.Local
更快? (不运行此应用程序的所有客户端都将是一个快速的LAN上。)
你为什么不干脆从第一个查询并使用它保存字符串列表。
List<string> cities = db.Cities.Select( x=>x.CityName).ToList();
当地可能因为选择,这可能会做一些一致性检查的速度较慢。
我走的源Local
使用属性ReSharper的的方便的功能。 你会首先看到的通话DetectChanges
这可能不是你的问题,如果你正在运行的所有是上述三行。 但随后EF用于创建一个新的ObservableCollection Local
,并通过项目来填充它的项目。 无论是那些可以在第一次通话成本。
直接对查询DbSet
将路由到EF数据库提供商,我相信直接访问内部本地高速缓存。
下面的扩展方法将返回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
调用.QuickLocal
含19679个实体DbSet需要9毫秒,而调用.Local
发生在第一次调用2121毫秒。