我的应用程序中与数据库的首次连接(EF 6.2,代码优先)非常慢,
有没有办法修改我的OnModelCreating
的{{1}}部分:
DbContext
在调试模式下,我看到这是初始化连接需要几十秒的原因...
答案 0 :(得分:2)
由于EF 编译您的模型并在内存中生成映射视图,因此第一个实体框架查询总是很慢。
您可以使用EF Power Tools预先生成那些映射视图。该here in docs.microsoft.com的文档。
为了加载这些视图,您需要创建一个自定义DbConfiguration类,如下所示:
public class MyDbConfiguration : DbConfiguration
{
public MyDbConfiguration() : base()
{
var path = Path.GetDirectoryName(this.GetType().Assembly.Location);
SetModelStore(new DefaultDbModelStore(path));
}
}
用法:
[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext
{
}
有关DbConfiguration的更多信息:here
如果应用程序未在Azure SQL中运行,您可以做的其他事情是使用这样的CustomManifestTokenResolver
public class CustomManifestTokenResolver : IManifestTokenResolver
{
public string ResolveManifestToken(DbConnection connection)
{
return "2012";
}
}
要使用它,必须将其添加到DbConfiguration类
public class MyDbConfiguration : DbConfiguration
{
public MyDbConfiguration() : base()
{
var path = Path.GetDirectoryName(this.GetType().Assembly.Location);
SetModelStore(new DefaultDbModelStore(path));
SetManifestTokenResolver(new CustomManifestTokenResolver());
}
}
启动过程中的另一个性能问题是EF程序集的及时编译。您可以使用ngen解决此问题(假设您的程序集位于bin \ release文件夹中。
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install .\bin\release\EntityFramework.dll
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install .\bin\release\EntityFramework.dll
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install .\bin\release\EntityFramework.SqlServer.dll
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install .\bin\release\EntityFramework.SqlServer.dll
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install .\bin\debug\EntityFramework.dll
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install .\bin\debug\EntityFramework.dll
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install .\bin\debug\EntityFramework.SqlServer.dll
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install .\bin\debug\EntityFramework.SqlServer.dll
对于一般的EF绩效问题,我确实有一个repository at github,在这里我演示了常见问题以及这些问题的解决方案。
更新:添加了启动性能技巧
我们在软件中使用的方法是在启动期间执行空查询。假设我们有一个名为MyContext
的上下文和一个名为Customers
的DbSet,我们将在启动期间编写如下代码:
using(var db = new MyContext())
{
db.Customers.Where(x=> x.Id < 0).ToList(); // There are no negative Ids, so this will always be and empty list
}
这会将您的初始化代码移至应用程序的启动阶段。因此,用户不会对系统中的第一个实际查询有较慢的体验。您甚至可以异步执行该操作。您只需要确保没有其他线程同时调用Context,因为DbContext不是ThreadSafe。
答案 1 :(得分:0)
您可以删除反射部分,而只需手动指定类型。反射是一项缓慢的任务,您不能期望使用反射的东西能带来快速的体验,但是因为它仅用于第一个连接,所以我个人不在乎,如果启动速度不是那么关键。