2013-12-21 45 views
3

下面是一個簡單linq查詢我在實體框架執行實體框架 - 潛在的SQL語句

db.Responses.FirstOrDefault(r => r.QuestionId.Equals(「1.1.1」) && r.User.Id.Equals(user.Id) && !r.IsDeleted); 

這裏QuestionIdvarchar數據類型列,db是上下文對象。

我解僱了實體Profiler來看看發生了什麼引擎蓋下面的SQL查詢下發生的事情似乎有一堆語句似乎有點畫蛇添足

/* 1 */ SELECT TOP (1) * 
/* 2 */ FROM [dbo].[Responses] AS [Extent1] 
/* 3 */ WHERE ((([Extent1].[QuestionId] = '1.1.1' /* @p__linq__0 */) 
/* 4 */  AND (NOT ([Extent1].[QuestionId] IS NULL 
/* 5 */    OR '1.1.1' /* @p__linq__0 */ IS NULL))) 
/* 6 */  OR (([Extent1].[QuestionId] IS NULL) 
/* 7 */   AND ('1.1.1' /* @p__linq__0 */ IS NULL))) 
/* 8 */ AND ([Extent1].[UserId] = 1 /* @p__linq__1 */) 
/* 9 */ AND (1 /* @p__linq__1 */ IS NOT NULL) 
/* 10 */ AND ([Extent1].[IsDeleted] <> cast(1 as bit)) 

通知所有額外的代碼行4-7 ,改變QuestionIdnull簡化了查詢作爲這樣

/* 1 */ SELECT TOP (1) * 
/* 2 */ FROM [dbo].[Responses] AS [Extent1] 
/* 3 */ WHERE ([Extent1].[QuestionId] = '1.1.1' /* @p__linq__0 */) 
/* 4 */ AND ('1.1.1' /* @p__linq__0 */ IS NOT NULL) 
/* 5 */ AND ([Extent1].[UserId] = 1 /* @p__linq__1 */) 
/* 6 */ AND (1 /* @p__linq__1 */ IS NOT NULL) 
/* 7 */ AND ([Extent1].[IsDeleted] <> cast(1 as bit)) 

所以,問題是爲什麼不把實體框架中所有額外的代碼? 爲什麼是4號線&線6必要,在where子句中唯一的相關陳述線3,5和7,

我試圖優化我的SQL語句和爲什麼實體框架正在做的事情什麼想法方式會有所幫助。我在Visual Studio 2013中使用EF6。

+0

如何比較值:'r.QuestionId ==「1.1.1」'? –

+0

@WiktorZychla r.QuestionId ==「1.1.1」沒有區別,既不.Equals和「==」都是等價的,r.QuestionId ==「1.1.1」代碼保持不變。 – usr28765526

回答

2

這是因爲字符串'1.1.1'作爲sql命令參數傳遞,而SQL生成器對參數的值一無所知。 Ef不會根據值生成不同的報表。即使傳遞值爲null,語句也必須正確。

如果列和參數值都爲空,並且列可爲空,則Equals必須爲true。當它不可爲空時,只有當傳遞值不爲空時它纔可以爲真。

EF所做的每件事情都是100%有效的,並且它的實現非常正確。不要試圖優化,除非你得到錯誤的結果。

+0

我不認爲這意味着很大的性能改進,但是有什麼方法可以避免EF生成這些不知何故的樸素語句嗎? – ecampver

+0

@ e.campver如果邏輯錯誤,性能沒有用處,那麼EF生成具有顯式空值檢查的語句將執行得更好,因爲查詢分析器將省略對空值的額外條件檢查。 –

3

線條:

/* 3 */ WHERE ((([Extent1].[QuestionId] = '1.1.1' /* @p__linq__0 */) 
/* 4 */  AND (NOT ([Extent1].[QuestionId] IS NULL 
/* 5 */    OR '1.1.1' /* @p__linq__0 */ IS NULL))) 

應該考慮到在C#/ VB.NET和SQL之間空比較在語義的差異。您可以使用DbContext.Configuration.UseDatabaseNullSemanticsObjectContextOptions.UseCSharpNullComparisonBehavior來控制行爲。你可以找到更多的細節herehere