J R*_*ose 5 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()
Run Code Online (Sandbox Code Playgroud)
现在我无法摆弄数据模型.但对于背景,基本上每个表都是一个'表单'.
SQL Server Profiler输出基本上是一个带表的大UNION,但执行速度非常快,所以我不认为问题是表格布局/键...
除了在启动时加热EF,我希望我遗漏一些基本的东西?看起来编译查询的管道非常黑盒子?有没有办法挂钩查询准备过程,看看有什么进展?(也许比抓住源头更不强烈...... :)
我认为你有两个选择:
使用已知的 sqlQuery,并仅针对这一查询通过 DbContext 将其作为原始 sql 执行,如下所示:
datasource.Component.SqlQuery("...").ToList();
Run Code Online (Sandbox Code Playgroud)您可以使用返回的委托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);
Run Code Online (Sandbox Code Playgroud)
然后在您的代码中您可以使用Invoke查询:
using(var datasource = new MyContext())
{
var result = CompiledQuery.Invoke(datasource,2).ToList();
}
Run Code Online (Sandbox Code Playgroud)第二种选择可能最适合您。从 .NET 4.5 开始,您的所有查询都会自动缓存为 Func,如上所述,这解释了为什么它第二次运行顺利。手动创建委托应该可以在您第一次运行查询时解决您的问题。
| 归档时间: |
|
| 查看次数: |
1262 次 |
| 最近记录: |