0

我有一个 Linq 查询,它使用硬整数值在大约一分钟(第一次)内返回 LinqPad。但是,当我将这些硬整数值转换为局部变量时,需要很长时间(超过 20 分钟)。

我的基本问题是:

  • 为什么/如何不同的 SQL 查询会导致这么多延迟?
  • 我可以防止这种不同的 SQL 查询吗?

在我试图解决这个问题时(见下文),我遇到了这些问题:

  • 我该如何使用DefaultQueryPlanCachingSettingor EnablePlanCaching
  • 如何抑制/防止查询编译/优化?
  • 如何验证我是否在使用 EF5?

查询差异似乎已经被注意到,并且在对该问题的回答中解释了原因。我也有这个查询差异,我看到一个额外的子 SELECT(和一些额外的 JOIN)。并且查询使用参数 ( [Extent6].[SomeThingId] = @p__linq__0) 而不是硬整数值 ( 4 = [Extent6].[SomeThingId])

但是,我不确定为什么这会是一个问题,以及如何防止它。(我知道在提供查询或数据库布局时答案可能会更容易,但是这种敏感材料,我的问题仍然是一样的......)

我假设问题出在使用参数时编译/执行计划中的一些“优化”。我正在尝试使用此建议来打开 L2E 的自动编译

 db.ContextOptions.DefaultQueryPlanCachingSetting = false;
 //(db as IObjectContextAdapter).ObjectContext.DefaultQueryPlanCachingSetting = false;

我无法让它工作,所以我试图找出我是否可以使用也提到的 [ ObjectQuery.EnablePlanCaching = false;],但我找不到在哪里/如何使用它。(我无法将我IQueryable的转换为ObjectQuery,也无法转换为我的上下文。)有人知道如何使用DefaultQueryPlanCachingSettingorEnablePlanCaching吗?

我尝试的另一件事是从常量值 Linq 中获取 SQL,并在其中引入一些 SQL 变量。这也很好,所以我尝试将它转换为一个存储过程,我可以从 EF 调用它。但是现在存储过程也需要很长时间才能运行。

我(也)想知道我是否真的有 EntityFramework 5。(这是我第一个使用 Linq、EntityFramework 和 ASP.MVC 的项目。)但我已经把它变成了一个单独的问题。

更新:我更改了“常规”存储过程:

SELECT ... WHERE @Id  = [Extent6].[SomeThingId] ...

进入带有动态 SQL 语句的存储过程:

@sql = 'SELECT ... WHERE ' + CAST(@Id AS VARCHAR) + ' = [Extent6].[SomeThingId] ...';
EXEC (@sql);

使用这个“动态”存储过程,我确实得到了非常快速的结果。而且由于参数将是相当恒定的(它们可能会在每天一次和每周一次之间变化),我认为这种缺乏优化/缓存对于性能来说是可以的。(但是,我不喜欢将业务逻辑放在存储过程中。)

4

1 回答 1

1

我发现了 Stuart Leeks 的这篇关于Entity Framework 5 控制自动查询编译的帖子。它提到它DefaultQueryPlanCachingSetting没有通过 EF5 的候选发布,您需要改为EnablePlanCaching在 ObjectSets 上设置属性。它也有一个简单的例子和​​一个方便的扩展方法的建议。我将引用 Stuart Leeks 的示例,因为“常规” MSDN还没有提供一个。您可以查看他的博客以了解扩展方法。

ObjectQuery<Customer> customersNoCache = context.Customers;
customersNoCache.EnablePlanCaching = false;
var query1 = from customer in context.Customers
             where customer.Country == "UK"
             select customer;

编辑:我实际上必须添加更多代码才能从 aDbSetObjectQuery. 与前面的例子一致,Customer这看起来像:

ObjectContext lObjectContext = ((IObjectContextAdapter)this).ObjectContext;
ObjectQuery<Customer> lDocCatgNoCache = lObjectContext.CreateObjectSet<Customer>();

但是生成的 SQL 仍然包含参数优化。我的猜测是,它 EnablePlanCaching只会抑制从 Linq 生成 SQL 的缓存,甚至不考虑 SQL 端的缓存?

(不幸的是,我没有时间进一步研究/测试。我一起实现了“动态”存储过程,并完成了这个项目。)

于 2013-04-08T07:33:20.853 回答