2014-12-31 26 views
0

看完後:http://forums.devart.com/viewtopic.php?f=31&t=22425&p=74949&hilit=IQueryable#p74949 看起來我應該用IQueryable來判斷一個實體的子表是否有記錄。查看實體的子表是否包含任何記錄的最快方法

我最初的嘗試是這樣的: Ace.DirDs.Any();

這行代碼(或類似的代碼行)可能會運行數百次,並導致巨大的性能問題。

所以從閱讀以前的帖子在上面的鏈接,我想我會嘗試這樣的:

IQueryable<DirD> dddd = CurrentContext.DirDs 
    .Where(d => d.AceConfigModelID == ace.ID).Take(1); 
bool hasAChild = dddd.Any(); 

會不會有更好的辦法?

回答

3

不需要Take(1)。另外,這個輸入更短。

bool hasAChild = CurrentContext.DirDs.Any(d => d.AceConfigModelID == ace.ID); 
+0

我遇到了性能問題。上面的代碼可以運行數百次。在我以前的代碼中(在我發佈的代碼之前),我發現我創建了一個IEnumerable,並將數千條記錄加載到內存中,然後查看是否存在。你的代碼是否阻止了這種情況發生? – ashlar64

+1

您需要確保您擊中了IQueryable而不是IEnumerable。 IEnumerable將導致工作在內存中完成,而不是在數據源上完成。 – Shoe

+0

我們需要看看'CurrentContext.DirDs'是什麼類型。 –

1

我可能是錯的,但我認爲Any()仍然會從數據庫服務器會在第一行的初始Read()返回給客戶端。你可能會更好地得到一個Count所以你只能得到一個回數:

bool hasAChild = CurrentContext.DirDs.Count(d => d.AceConfigModelID == ace.ID) > 0; 

通過這個不出現的方式來尋找一個子表只是DirDs

+0

對不起,我最初的嘗試是在看一個子表,這是一個巨大的性能問題。所以我試圖使用IQueryable來避免這個問題。 – ashlar64

+0

'Count()'將導致服務器上的I/O比需要更多。 'Any()'不會返回任何數據。 –

1

在您的示例中,您將IQueryable實現爲IEnumerable,因此將執行整個查詢,然後您只是在結果中取第一行。以前的例子答案都會比這個快得多。由於同時存在屬性Count和方法Count(),因此在使用Count時要小心。爲了避免你原來的問題(如果你選擇Count路由),你需要像使用Rhumborl的例子一樣使用Count()方法,否則它會執行查詢併爲你提供IEnumerable的Count屬性返回。 Count()方法本質上轉換爲SQL COUNT,而Any()方法轉換爲SQL EXISTS(至少在使用Microsoft SQL Server時)。根據你的後端數據庫是什麼以及你使用的是哪個版本的EF,在這個層次上可以比另一個更高效。

我的投票將總是默認爲任何()和探索計數(),如果你遇到性能麻煩。在數據庫級別使用Count()方法仍然會帶來性能成本,但這仍取決於您使用的數據庫。

下面是一個很好的相關答案:Linq To Entities - Any VS First VS Exists

相關問題