2012-10-09 60 views
3

我有這樣的代碼:爲什麼實體框架生成緩慢的過度工程SQL?

DbSet<TableName> table = ...// stored reference 

var items = from n in table where 
      n.Name.ToUpper().Contains(searchString.ToUpper().Trim()) 
      select n; 
WriteToLog(items.ToString()); 

最後一行輸出所生成的SQL。下面是我得到:

SELECT 
    [Extent1].[Name] AS [Name], 
    // all the other columns follow 
FROM (SELECT 
    [TableName].[Name] AS [Name], 
    // all the other columns follow 
FROM [dbo].[TableName] AS [TableName]) AS [Extent1] 
WHERE (CAST(CHARINDEX(LTRIM(RTRIM(UPPER(@p__linq__0))), UPPER([Extent1].[Name])) AS int)) > 0 

你看,有SELECT -from- SELECT雖然它完全是多餘的 - 一個SELECT就剛好夠。使用EF的代碼運行超過半分鐘,並在該查詢超時,但表格很小。

爲什麼這個過度工程化的SQL查詢生成了,我該如何讓EF生成一個更好的查詢?

+7

查詢優化器將對此做簡短的工作。我認爲它會生成不可讀的代碼,但這不是問題,因爲它不是爲了實現這個目的而設計的。如果你有一些測量的證據表明SQL很慢,那會很好,但我會想象它不是,而你錯了。你做? –

+1

至於如何改善它,請參閱http://weblogs.asp.net/scottgu/archive/2012/07/19/entity-framework-and-open-source.aspx –

+0

@Kieren Johnstone:好的,查詢運行時間超過半分鐘,並超時,雖然它相當微不足道。 – sharptooth

回答

7

它通過轉換表達式樹來生成結果SQL。它似乎被過度工程化(例如,使用子查詢)作爲它完成該轉換的副作用。 轉型的細節是專有的和複雜的,結果不應該是人類可讀的。

這個問題並不完全清楚 - 而且您正試圖解決一個我認爲可能不成問題的問題。嘗試將生成的查詢與您自己的查詢進行比較 - 我猜猜查詢優化程序將簡化這種簡單優化的工作。

我的猜測(這可能是你能得到的最好的答案,除非LINQ to Entities MS dev出現)是他們正在做的事情是:產生最有效的查詢,但讓頭部受傷 - 將查詢優化到他們已經投入了數百或數千個工作日的難題:SQL Server中的查詢優化器。

3

它做了一個額外的Select但選擇沒有成本相關。你可以看到估計的查詢計劃,它會顯示0%成本。這樣做是因爲EF與各種RDBMS系統(如Oracle,SQL服務器)兼容,並且可以確保最大的兼容性。

但我同意Entity Framework生成UGLY sql。你給出的例子是一個非常簡單的Linq查詢,當你的查詢開始變得複雜時,你會看到更多的醜陋。

1)雖然這可能會或可能不會回答您的回答,我會說使用微ORM像PetaPoco:

https://github.com/toptensoftware/PetaPoco

或Dapper.Net

https://github.com/SamSaffron/dapper-dot-net

我一直在使用它在我的一個項目中,並且我完全滿意於使用普通Ado.Net獲得的原始速度。

2)我的第二個建議是始終使用存儲過程ATLEASTSelect語句。對於插入,更新和刪除,你可能應該使用EF並利用變更跟蹤機制,這將節省你的時間從編寫乏味的查詢,但至少爲您應該嘗試使用普通SQL的選擇語句,並且給你更多的自由,產生。

+0

好點,但是混合SQL和EF在我看來很麻煩 –

+0

@KierenJohnstone真的取決於自定義SQL查詢結果的預期用途。例如。我可以顯示一個存儲過程的結果列表,該列表給出了比依靠EF進行更有效的查詢更多的控制。如果我實際上沒有使用存儲過程的結果然後通過EF將更新保存回數據庫,我沒有看到任何問題。 –

相關問題