2011-04-11 100 views
3

我不是任何方式的LINQ高級用戶,但可以在基本級別上摸索我的方式。我有一個關於LINQ如何表達它的查詢「策略」的問題。我會盡我所能解釋這一點,並通過記憶寫出一個非常愚蠢的例子。LINQ執行多個查詢而不是單個「已加入」查詢

我有一個包含多個數據庫視圖的數據模型。比方說,有意見一欄結構如下:

PersonView

PersonViewId | Surname | GivenName | OtherViewId 
------------------------------------------------ 

奧瑟維尤查看

OtherViewId | PersonViewId | Name 
--------------------------------- 

設置主鍵的視圖後(PersonView.PersonViewId/OtherView.OtherViewId)和設置適當的字段是非可變的,我創建一個PersonView.PersonViewId(父)與OtherView.PersonViewId(Child)之間的關聯。我將其設置爲「一對一」,並寫一些代碼來使用它:

StringBuilder s = new StringBuilder(); 
foreach(PersonView p in dc.PersonViews) 
{ 
    s.AppendLine(p.OtherViews.Name + "<br />"); 
} 

注意到性能極差,我異型數據庫,發現它在foreach做一個查詢每個PersonView年代聲明。

此時我重新編寫了查詢,並用LINQ查詢中的JOIN替換了DBML中的關聯,對數據庫進行了概要分析,並且按預期查詢了數據庫,只查詢了一次。

我認爲這是與事實,然後數據庫實際上被查詢,但不知道該在哪裏調試。有人能指出我在這方面的正確方向,以幫助我提高使用關聯的性能,還是我堅持使用JOIN來完成我所需要的功能?

謝謝:)

+0

您應該檢查由LINQ生成的代碼。 – 2011-04-11 21:15:39

回答

4

這是由延遲加載造成的 - 你可以得到解決,通過應用LoadWith()(EF的Include()對LINQ的相當於SQL),然後做查詢算賬:

var dlo = new DataLoadOptions(); 
dlo.LoadWith<PersonView>(p => p.OtherViews); 
dc.LoadOptions = dlo; 
//your query here 
1

這是延遲加載LINQ-2-SQL的過錯,中(又名延遲加載)功能,當你在你的OtherViews表做p.OtherViews.Name它做一個查詢。

有一對夫婦的方式來對付它,一個是關斷延遲加載:

dc.DeferredLoadingEnabled = false; 

另一種是讓你在你的結果想要的一切的投影,並使用投影:

var people = from p in dc.PersonViews 
      select new { 
       Person = p, 
       Name = p.OtherViews.Name 
      }; 

再有就是BrokenGlass的建議下,我不知道到現在爲止:-)

1

你看到這種情況的原因是LINQ的使用延遲加載這些關係。換句話說,Linq在你真正嘗試和使用它之前不會加載關聯。

這可以提高性能,因爲如果您不總是需要關聯,那麼您不會執行不必​​要的JOIN,而且您也不會檢索不需要的數據。

雖然如果你確定你需要這些數據並且它不斷髮出請求,它可能會損害性能。

您可以通過保持原有關聯來解決此問題,但使用DataLoadOptions。例如:

var dc = new DataContext(); 
dc.DeferredLoadingEnabled = false; 

DataLoadOptions loadOptions = new DataLoadOptions(); 
loadOptions.LoadWith<PersonView>(o => o.OtherView); 

dc.LoadOptions = loadoptions; 

現在,無論何時您查詢一個PersonView,它都會自動加載OtherView關係。

這種方法的好處是您可以在需要時打開和關閉它。