2013-04-04 83 views
0

我有一個Linq-query,在大約一分鐘(第一次)使用硬整數值返回LinqPad。 但是,當我將這些硬整數值轉換爲局部變量時,需要永久(超過20分鐘)。如何防止EF-Linq爲變量和常量生成不同的查詢?

我的基本問題是:

  • 爲什麼/如何將不同的SQL查詢造成這麼多的延遲?
  • 我可以阻止這種不同的SQL查詢嗎?

在我試圖解決這個問題(見下面),我遇到了這樣的問題:

  • 我如何使用DefaultQueryPlanCachingSettingEnablePlanCaching
  • 我該如何抑制/阻止查詢編譯/優化?
  • 如何驗證我是否使用EF5?

query-difference似乎已經注意到了,在回答這個問題的why is explained。我也有這種查詢差異,我看到一個額外的子SELECT(和一些額外的JOIN)。和查詢使用參數([Extent6].[SomeThingId] = @p__linq__0),而不是硬整數值(4 = [Extent6].[SomeThingId]

但是,我不知道爲什麼這將是一個問題,以及如何防止它。 (據我所知,提供查詢或DB-佈局,但這種敏感材料的時候,我的問題是一樣的答案可以更容易...)

我是假設的問題是一些使用參數時編譯/執行計劃中的'優化'。我試圖用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,也不是我的背景。)有誰知道如何使用DefaultQueryPlanCachingSettingEnablePlanCaching

我試過的另一件事是從常量值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); 

有了這個 '動態' 的存儲過程我獲得非常快速的結果。而且由於參數會保持不變(它們可能會在每天一次和每週一次之間改變),所以我認爲這種優化/緩存的缺乏對於性能來說是可以接受的。 (但是,我不喜歡把存儲過程中的業務邏輯。)

+1

郵政查詢。 – 2013-04-04 16:29:35

+0

你可能使查詢在C#中執行,而不是 - 發佈您的查詢 – NSGaga 2013-04-04 17:07:31

+0

我不認爲在C#中執行是問題。我認爲我關於存儲過程中動態查詢的更新也說明了這一點。我仍然懷疑我是否應該繼續採用這種不合時宜的「動態過程」。 – 2013-04-05 09:17:44

回答

1

我發現這個職位由Stuart韭菜約Entity Framework 5 controlling automatic query compilation。它提到DefaultQueryPlanCachingSetting沒有超過EF5的Release Candidate,您需要改爲在ObjectSets上設置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 -example這一行看起來像:

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

但是生成的SQL仍然包含參數優化。我的猜測是EnablePlanCaching只能抑制從Linq生成SQL的緩存,它甚至不考慮SQL端的緩存?

(不幸的是,我沒有時間去reasearch /進一步測試任何我去與實施「動態」的存儲過程一起,並且完成了這個項目。)