实体框架6自动编译查询

时间:2016-01-13 02:28:53

标签: c# entity-framework

我的查询在首次执行时花了一些时间。所有后续执行都非常快(即使使用不同的数据)。我相信第一次执行EF是自动编译查询(构建查询计划,等等等等),第二次调用是使用编译版本。哪个好,除了第一个用户。那可怜的汁液被搞砸了。在糟糕的一天,EF执行将是2分钟(71ms实际上与SQL Server通信 - 使用SQL Server Profiler验证。)

我已经开始预先编译了这些视图,这些视图在初始缓存时节省了一些时间。

基本上查询看起来像这样

dataSource.Component
    .Include(t => t.Table1)
    ... 37 tables later ...
    .Include(t => t.Table38)
    .Where(n=>n.Id == id).First()

现在我无法摆弄数据模型。但是对于背景,基本上每个表都是'Form。'

SQL Server Profiler输出基本上是一个带表的大UNION,但执行速度非常快,所以我认为问题不在于表格布局/键......

除了在启动时加热EF,我希望我遗漏一些基本的东西?看起来编译查询的管道非常黑盒子?有没有办法挂钩查询准备过程,看看有什么进展? (也许比抓住源头更不那么激烈......)。

1 个答案:

答案 0 :(得分:2)

我认为你有两个选择:

  1. 使用已知的sqlQuery,只为这一个查询通过DbContext执行原始sql,如文档here所示:

    datasource.Component.SqlQuery("...").ToList();
    
  2. 您可以使用返回IQueryable的委托来预编译您的表达式:

    public static Func<MyContext,int,IQueryable<Component>> CompiledQuery = (ctx,id) => 
           ctx.Include(c => c.Table1)
              .Include(c => c.Table2)
              ...
              .Include(c => c.Table38)
              .Where(n => n.Id == id);
    

    然后在您的代码中,您可以使用Invoke来使用查询:

    using(var datasource = new MyContext())
    {
        var result = CompiledQuery.Invoke(datasource,2).ToList();
    }
    
  3. 第二种选择可能最适合你。从.NET 4.5开始,所有查询都会自动缓存为Func,如上所述,这解释了为什么它第二次运行顺利。手动创建委托应在第一次运行查询时解决您的问题。