我使用實體框架和我需要檢查是否有名稱=「XYZ」的產品存在...LINQ到實體 - 任何VS首先VS已存在
我想我可以用任何(),是否存在( )或First()。
哪一個是這種情況的最佳選擇?哪一個表現最好?
謝謝你,
米格爾
我使用實體框架和我需要檢查是否有名稱=「XYZ」的產品存在...LINQ到實體 - 任何VS首先VS已存在
我想我可以用任何(),是否存在( )或First()。
哪一個是這種情況的最佳選擇?哪一個表現最好?
謝謝你,
米格爾
任何在數據庫級別轉換爲「Exists」。首先轉換爲Select Top 1 ...之間,Exists將執行First,因爲實際對象不需要提取,只有布爾結果值。
至少你沒有問過.Where(x => x.Count()> 0),它需要對整個匹配集進行評估和迭代,然後才能確定你有一條記錄。任何短路的請求,可以顯着更快。
Any()
和First()
使用與IEnumerable
它給你懶洋洋地評價事情的靈活性。但是Exists()
需要列表。
我希望這可以爲您解決問題並幫助您決定使用哪一個。
有人會認爲Any()
給出了更好的結果,因爲它轉化爲一個EXISTS
查詢......但EF是非常破碎,產生這種(編輯):
SELECT
CASE WHEN (EXISTS (SELECT
1 AS [C1]
FROM [MyTable] AS [Extent1]
WHERE Condition
)) THEN cast(1 as bit) WHEN (NOT EXISTS (SELECT
1 AS [C1]
FROM [MyTable] AS [Extent2]
WHERE Condition
)) THEN cast(0 as bit) END AS [C1]
FROM (SELECT 1 AS X) AS [SingleRowTable1]
相反的:
SELECT
CASE WHEN (EXISTS (SELECT
1 AS [C1]
FROM [MyTable] AS [Extent1]
WHERE Condition
)) THEN cast(1 as bit)
ELSE cast(0 as bit) END AS [C1]
FROM (SELECT 1 AS X) AS [SingleRowTable1]
...基本上加倍查詢成本(對於簡單查詢;對於複雜查詢更是如此)
我發現使用.Count(condition) > 0
幾乎總是更快(成本與正確書寫的EXISTS
查詢完全一樣)
一個有趣的觀察,但我恐怕這個答案過於簡單化的事情到可能誤導開始點。 [看我的回答](http://stackoverflow.com/a/12439909/120955)。 – StriplingWarrior
好的,我不打算對此加以考慮,但迭戈的回答讓事情變得複雜化,我認爲有些額外的解釋一切順利。
在大多數情況下,.Any()
會更快。以下是一些例子。
Workflows.Where(w => w.Activities.Any())
Workflows.Where(w => w.Activities.Any(a => a.Title == "xyz"))
在上面的兩個例子中,Entity Framework產生了一個最佳查詢。 .Any()
調用是謂詞的一部分,而Entity Framework處理得很好。但是,如果我們的結果集這樣的.Any()
部分結果:
Workflows.Select(w => w.Activities.Any(a => a.Title == "xyz"))
...突然實體框架決定創建條件的兩個版本,因此查詢不盡可能多的工作,它的兩倍真的需要。但是,下面的查詢是沒有任何好轉:
Workflows.Select(w => w.Activities.Count(a => a.Title == "xyz") > 0)
鑑於上述情況查詢,實體框架仍然會創造條件的兩個版本,再加上它也將需要的SQL Server做一個實際計數,這意味着它一旦發現物品就不會短路。
但如果你只是比較這兩個查詢:
Activities.Any(a => a.Title == "xyz")
Activities.Count(a => a.Title == "xyz") > 0
...這將是更快?這取決於。
第一個查詢產生一個低效率的雙重條件查詢,這意味着它將花費兩倍的時間。
第二個查詢強制數據庫檢查表中沒有短路的每個項目,這意味着它最多可能需要比其所需時間長N
,這取決於在找到匹配之前需要評估多少項目。讓我們假設該表有10,000項:
Title
和關鍵列上的索引,則該查詢將花費大約一半的時間作爲第一個查詢的。因此,在總結,如果你是:
那麼你可以指望.Any()
要花費兩倍於.Count()
。例如,查詢可能需要100毫秒而不是50,或者10而不是5。
的其他情形.Any()
至少應該儘可能快是,並可能數量級的速度比.Count()
。
無論,直到您確定這實際上是產品性能不佳的原因,您應該更關心易於理解的內容。 .Any()
更清楚簡明地說明你真正想要弄清楚什麼,所以堅持這一點。
如果您試圖解決Any()錯誤(?),而不是將其轉換爲'Count()> 0',我會使用'FirstOrDefault()!= null'。 – Mormegil
@Mormegil:一個有趣的想法。但是我測試了它,並且創建了一個更瘋狂的查詢,並帶有兩個外部應用的select語句。所以它實際上並沒有解決問題,並且它使代碼(在我看來)略微不那麼清晰。 – StriplingWarrior
+1「,除非你確定這實際上是產品性能低下的根源,你應該更關心容易理解的東西。」評論 –
+1。澄清:統計整個匹配集是在數據庫級完成的,因此它不會將對象提取到應用程序中。仍然'.Any()'更簡單,它將勝過'.Where(x => x.Count> 0)',所以它應該是首選。 – StriplingWarrior
@StriplingWarrior在數據庫中完成計數是事實,但由於EF的可怕查詢生成,它仍然比計數還要糟糕。看到我的答案。 –