每次编译后第一次加载实体框架的速度都很慢

Leo*_*oLi 43 c# sql-server entity-framework

正如标题所示,我在使用实体框架对SQL Server数据库进行第一次查询时遇到问题.我试过寻找答案,但似乎没有人真正找到解决方案.

测试是在使用Entity Framework 6的Visual Studio 2012中完成的,我还使用了T4视图模板来预编译视图.该数据库位于SQL Server 2008上.我们有大约400个POCO(400个映射文件),在数据库表中只有100行数据.

捕获后是我的测试代码和结果.

static void Main(string[] args){
    Stopwatch st=new Stopwatch();
    st.Start();
    new TestDbContext().Set<Table1>.FirstOrDefault();
    st.stop();
    Console.WriteLine("First Time "+st.ElapsedMilliseconds+ " milliseconds");

    st.Reset();
    st.Start();
    new TestDbContext().Set<Table1>.FirstOrDefault();
    st.stop();
    Console.WriteLine("Second Time "+st.ElapsedMilliseconds+ " milliseconds");
}
Run Code Online (Sandbox Code Playgroud)

检测结果

First Time 15480 milliseconds
Second Time 10 milliseconds
Run Code Online (Sandbox Code Playgroud)

Mik*_*son 39

在第一个查询中,EF编译模型.对于这么大的模型,这可能需要一些时间.

以下是3条建议:http://www.fusonic.net/en/blog/2014/07/09/three-steps-for-fast-entityframework-6.1-first-query-performance/

总结:

  1. 使用缓存的db模型存储
  2. 生成预编译的视图
  3. 使用n-gen生成实体框架的预编译版本以避免抖动

我还要确保在执行基准测试时在发布模式下编译应用程序.

另一个解决方案是查看拆分DBContext.400个实体很多,使用较小的块应该更好.我没有尝试过,但我认为可以逐个构建模型,这意味着没有一个负载需要15秒.请参阅Julie Lerman的这篇文章https://msdn.microsoft.com/en-us/magazine/jj883952.aspx

  • @MikaelEliasson文章中介绍的工具("_nuget包:实体框架6._的交互式预生成视图"和"github_上的_DbModelStore分支")在2014**之后不会更新.我们现在可以使用哪些替代工具或方法? (4认同)

Yep*_*kai 12

使用 EF Core,您可以在调用后尽早作弊并加载模型services.AddDbContext(您可能也可以使用 EF6 做类似的事情,但我还没有测试过)。

services.AddDbContext<MyDbContext>(options => ...);
var options = services.BuildServiceProvider()
                      .GetRequiredService<DbContextOptions<MyDbContext>>();
Task.Run(() =>
{
    using(var dbContext = new MyDbContext(options))
    {
        var model = dbContext.Model; //force the model creation
    }
});
Run Code Online (Sandbox Code Playgroud)

这将在另一个线程中创建 dbcontext 的模型,同时完成应用程序的其余初始化(可能还有其他预热)和请求的开始。这样,它会更快地准备好。当您需要它时,EFCore 将等待模型尚未完成创建。它Model在所有 DbContext 实例之间共享,因此可以触发并忘记这个虚拟 dbcontext。

  • 根本不应该调用 `services.BuildServiceProvider()` [ASP.NET Core 中的依赖注入](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view= aspnetcore-3.1#recommendations)。您应该只从ConfigureServices中调用“services.AddDbContext&lt;MyDbContext&gt;(options =&gt; ...);”并将其注入到Configure“public voidConfigure(..., MyDbContext dbContext)”中,然后只调用“Task.Run( () =&gt; { _ = dbContext.Model; });` (2认同)
  • 我尝试过,但这在 EF Core 中不起作用,第一个查询仍然很慢。 (2认同)

All*_*ool 5

你可以尝试这样的事情:(它对我有用)

protected void Application_Start()
{

    Start(() =>
    {
        using (EF.DMEntities context = new EF.DMEntities())
        {
            context.DMUsers.FirstOrDefault();
        }
    });
}
private void Start(Action a)
{
    a.BeginInvoke(null, null);
} 
Run Code Online (Sandbox Code Playgroud)

实体框架 - 第一次查询很慢