我有一个Linq查询,它使用硬整数值在大约一分钟内(第一次)在LinqPad中返回。 但是,当我将这些硬整数值转换为局部变量时,它需要永远(超过20分钟)。
我的基本问题是:
在我试图解决这个问题时(见下文),我遇到了这些问题:
DefaultQueryPlanCachingSetting
或EnablePlanCaching
? query-difference似乎已经被注意到,而why is explained则回答了这个问题。我也有这个查询差异,我看到一个额外的子SELECT(和一些额外的JOIN)。查询使用参数([Extent6].[SomeThingId] = @p__linq__0
)代替硬整数值(4 = [Extent6].[SomeThingId]
)
但是,我不确定为什么这会是一个问题,我怎么能阻止它。 (我知道在提供查询或数据库布局时,可能更容易,但这种敏感材料,我的问题仍然相同......)
我在使用参数时假设问题来自编译/执行计划中的某些'优化'。我正在尝试使用this suggestion to turn of the auto-compilation for L2E:
db.ContextOptions.DefaultQueryPlanCachingSetting = false;
//(db as IObjectContextAdapter).ObjectContext.DefaultQueryPlanCachingSetting = false;
我无法让这个工作,所以我试图找出是否可以使用也提到的[ObjectQuery.EnablePlanCaching = false;
],但我找不到在哪里/如何使用它。 (我无法将IQueryable
转换为ObjectQuery
,也不能投放到我的上下文。)有人知道如何使用DefaultQueryPlanCachingSetting
或EnablePlanCaching
吗?
我尝试的另一件事是从常量值Linq中获取SQL,并在其中引入一些SQL变量。这也很好,所以我尝试在存储过程中转换它,我可以从EF调用。但是现在存储过程也需要很长时间才能运行。
我(也)想知道if I really have EntityFramework 5。 (这是我使用Linq,EntityFramework和ASP.MVC的第一个项目。)但我已经在另一个问题中解决了这个问题。
更新:我更改了“常规”存储过程:
SELECT ... WHERE @Id = [Extent6].[SomeThingId] ...
使用动态SQL语句进入存储过程:
@sql = 'SELECT ... WHERE ' + CAST(@Id AS VARCHAR) + ' = [Extent6].[SomeThingId] ...';
EXEC (@sql);
通过这种“动态”存储过程,我可以获得非常快速的结果。而且由于参数将相当稳定(它们可能会在每天一次和每周一次之间变化),我认为缺乏优化/缓存对于性能来说是可行的。 (但是,我不喜欢将业务逻辑放在存储过程中。)
答案 0 :(得分:1)
我发现Stuart Leeks关于Entity Framework 5 controlling automatic query compilation的这篇文章。它提到DefaultQueryPlanCachingSetting
没有超过EF5的Release Candidate,你需要在ObjectSet上设置EnablePlanCaching
属性。它还有一个简单的例子和一个方便的扩展方法的建议。我引用Stuart Leeks的例子,因为'常规'MSDN还没有提供。您可以在他的博客上查看扩展方法。
ObjectQuery<Customer> customersNoCache = context.Customers;
customersNoCache.EnablePlanCaching = false;
var query1 = from customer in context.Customers
where customer.Country == "UK"
select customer;
修改:实际上我必须添加更多代码to get from a DbSet
to an ObjectQuery
。与之前的Customer
一致 - 示例如下:
ObjectContext lObjectContext = ((IObjectContextAdapter)this).ObjectContext;
ObjectQuery<Customer> lDocCatgNoCache = lObjectContext.CreateObjectSet<Customer>();
但生成的SQL仍然包含参数优化。我的猜测是EnablePlanCaching
只抑制从Linq生成SQL的缓存,它甚至不考虑SQL端的缓存?
(不幸的是,我没有时间进行再研究/测试。我接着实施了'动态'存储过程,并完成了这个项目。)