我的查询在首次执行时花了一些时间。所有后续执行都非常快(即使使用不同的数据)。我相信第一次执行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,我希望我遗漏一些基本的东西?看起来编译查询的管道非常黑盒子?有没有办法挂钩查询准备过程,看看有什么进展? (也许比抓住源头更不那么激烈......)。
答案 0 :(得分:2)
我认为你有两个选择:
使用已知的sqlQuery,只为这一个查询通过DbContext执行原始sql,如文档here所示:
datasource.Component.SqlQuery("...").ToList();
您可以使用返回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();
}
第二种选择可能最适合你。从.NET 4.5开始,所有查询都会自动缓存为Func,如上所述,这解释了为什么它第二次运行顺利。手动创建委托应在第一次运行查询时解决您的问题。