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

时间:2015-05-24 13:06:09

标签: c# sql-server entity-framework

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

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

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

ng-click

测试结果

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");
}

7 个答案:

答案 0 :(得分:36)

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

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

摘要:

  1. 使用缓存的数据库模型商店
  2. 生成预编译的视图
  3. 使用n-gen生成实体框架的预编译版本以避免jitting
  4. 我还要确保在执行基准测试时在发布模式下编译应用程序。

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

答案 1 :(得分:2)

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

protected void Application_Start()
{

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

Entity Framework - First query slow

答案 2 :(得分:2)

使用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
    }
});

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

答案 3 :(得分:0)

这项工作对我来说:

using (MyEntities db = new MyEntities())                
{
   db.Configuration.AutoDetectChangesEnabled = false; // <----- trick
   db.Configuration.LazyLoadingEnabled = false; // <----- trick

   DateTime Created = DateTime.Now;

   var obj = from tbl in db.MyTable
      where DateTime.Compare(tbl.Created, Created) == 0
      select tbl;

   dataGrid1.ItemsSource = obj.ToList();
   dataGrid.Items.Refresh();
}

答案 4 :(得分:0)

如果您有很多未在c#上使用的表,请将它们排除在外。

添加部分类,添加以下代码,并在OnModelCreating上引用此函数

void ExcludedTables(DbModelBuilder modelBuilder)
{
    modelBuilder.Ignore<Table1>();
    modelBuilder.Ignore<Table>();
   // And so on
}

答案 5 :(得分:0)

对我来说,仅在第一个查询中使用AsParallel()即可解决问题。这将在多个处理器内核上(显然)运行查询。我随后的所有查询都保持不变,只是造成延迟的第一个查询。

我还尝试了预生成的映射视图https://docs.microsoft.com/en-us/ef/ef6/fundamentals/performance/pre-generated-views,但这并不能大大缩短启动时间。

答案 6 :(得分:-2)

我认为这不是一个很好的解决方案。 Ado.net看起来表现得更好。但是,这是我的意见。

或者看看它们。

https://msdn.microsoft.com/tr-tr/data/dn582034

https://msdn.microsoft.com/en-us/library/cc853327(v=vs.100).aspx