实体框架的第一个数据库连接缓慢

时间:2019-03-24 09:53:44

标签: c# entity-framework-6

我的应用程序中与数据库的首次连接(EF 6.2,代码优先)非常慢, 有没有办法修改我的OnModelCreating的{​​{1}}部分:

DbContext

在调试模式下,我看到这是初始化连接需要几十秒的原因...

2 个答案:

答案 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)

您可以删除反射部分,而只需手动指定类型。反射是一项缓慢的任务,您不能期望使用反射的东西能带来快速的体验,但是因为它仅用于第一个连接,所以我个人不在乎,如果启动速度不是那么关键。