2014-09-19 35 views
4

比方說,我有這樣一行:不包括導航性能和DB往返

var eggs = db.Nests.Single(b => b.id = 20).Birds.FirstOrDefault().Eggs; 

在我的探查器跟蹤,我看到有正在執行多個命令:

SQL:BatchString 
SELECT TOP (2) 
[Extent1].[id] 
... 
FROM [dbo].[Nest] AS [Extent1] 
WHERE 20 = [Extent1].[id] 
SQL:BatchCompleted 

RPC:Completed 
exec sp_executesql N'SELECT 
[Extent1].[Id] AS [Id], 
... 
FROM [dbo].[Bird] AS [Extent1] 
WHERE [Extent1].[NesId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=20 

RPC:Completed 
exec sp_executesql N'SELECT 
[Extent1].[Id] AS [Id], 
... 
FROM [dbo].[Egg] AS [Extent1] 
WHERE [Extent1].[BirdId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=13 

是否所有那些命令是在同一個請求中執行的,還是每個都有往返?

此外,可我得到確認,這是寫的最有效的方法上面:

var eggs = db.Nests.Include("Birds") 
      .Single(b => b.id = 20) 
      .Birds.Include("Eggs") 
      .FirstOrDefault() 
      .Eggs; 

還是會顯式連接比較好?

回答

2

首先,在第一個示例中獲得多個查詢是完全正常的。除非在第二個示例中使用Include(),否則訪問任何導航屬性都會生成新的SQL查詢。

我不知道你的數據庫架構的佈局方式,但假設Birds有一個外鍵Nests稱爲Id_Nest你可以重寫此查詢爲:

var eggs = db.Birds.Include("Eggs") 
        .First(x => x.Id_Nest == 20) 
        .Eggs 
        .ToList(); 

Include()產生大約相同的代碼作爲明確的join所以不需要擔心代碼不同。而對於往返,如果你的意思是在Web服務器和數據庫之間往返,那麼是的,每個查詢可能都是往返。如果連接保持打開狀態,這並不是什麼大問題。但最好是通過joinInclude()一次性獲得所需的所有內容,而不是一次打3次。

1

你在你的問題中所描述的行爲是lazy-loading功能,可幫助快速構建代碼工作一個典型的例子,但執行不佳因爲表現遠遠沒有達到最佳。作爲一個側面說明,我個人總是建議完全停用延遲加載。

所有這些命令是在相同的請求中執行還是爲 每個都有往返行程?

是的,每次請求都有一次往返。在你的例子中,這可能不是什麼大不了的事,但想象你的代碼是在一個循環內的......你將請求數(3)乘以迭代次數。你可以最終成千上萬的請求。

此外,可我得到確認,這是寫在上面的最有效的方式 :

這不是寫您的查詢的最有效方法。其實它可能不會編譯(你不能像你那樣使用Include)。

通常建議,最有效的方法是包括你的需要,那麼所有的導航性能,也只有這樣,使用單一ToList/Single/First或任何功能實際執行的執行查詢查詢和實現實體。所以你只有一個SQL請求。

對於您給出的具體示例,@Radu Porumb建議可能是將生成最簡單/高效的SQL的查詢。當然,你必須使用探查器來驗證這個假設。

+0

Glimpse可能是一個更好的選擇 – 2014-09-22 19:59:15