2010-11-17 64 views
1

我發現this link這解釋了我的問題,並有一個答案,但似乎無法使其工作。LinqToSQL查詢loadwith性能

下面是我對DataLoadOptions:

 options.LoadWith<Support>(p => p.PostBase); 
     options.LoadWith<Support>(p => p.PostMaterial); 
     options.LoadWith<Support>(p => p.PostPosition); 
     options.LoadWith<Support>(p => p.PostSize); 
     options.LoadWith<Support>(p => p.PostType); 
     options.LoadWith<Support>(p => p.Signs); 
     options.LoadWith<Support>(p => p.SupportComments); 
     options.LoadWith<Support>(p => p.SupportInspections); 
     options.LoadWith<Support>(p => p.SupportPhotos); 
     options.LoadWith<Sign>(p => p.SignBacking); 
     options.LoadWith<Sign>(p => p.SignComments); 
     options.LoadWith<Sign>(p => p.SignCondition); 
     options.LoadWith<Sign>(p => p.SignDelineator); 
     options.LoadWith<Sign>(p => p.SignFace); 
     options.LoadWith<Sign>(p => p.SignIllumination); 
     options.LoadWith<Sign>(p => p.SignToSignObstructions); 
     options.LoadWith<Sign>(p => p.UniformTrafficControlCode); 
     options.LoadWith<SignToSignObstruction>(p => p.SignObstruction); 

我認爲這會給我的對象圖的一個很好的解釋。我試圖查詢符合特定搜索條件的支持對象(也許有人希望支持帖子類型的等等)。

如果我嘗試只返回所有支持,我得到約2200支持,它需要17k查詢。

我試圖在另一個問題中提到的分組解決方案,但我想知道如果我做錯了,或者我的情況太複雜。我刪除了搜索條件,並試圖返回所有支持。這導致約21k查詢並拉回約3000支持。這裏是我的查詢:

   var group = 
       from support in roadDataContext.Supports 
       join sign in roadDataContext.Signs on support.SupportID equals sign.SupportID 
       group sign by sign.Support 
       into signGroup 
       select signGroup; 

我只是想念一些簡單的東西嗎?謝謝。

+0

你爲什麼試圖在搜索查詢中取回所有數據*? *您找到*您正在尋找的'Support'後,您應該使用'LoadWith'。如果你實際上需要返回一個非規範化的表作爲你的搜索結果的一部分,你應該使用'Select'運算符並返回一個'x => new {x.PostBase.XXX等}顯示。還要考慮分頁 - 無論您如何獲取數據,3000行都不合適。 – 2010-11-17 18:53:59

+0

我會再次從頭開始:如果刪除所有LoadWith,會發生什麼情況:當時正在生成的SQL是什麼?之後開始調整 – Pleun 2011-02-22 17:59:44

回答

2

我們在L2S數據層中犯了同樣的錯誤。我們的負載選項在某些情況下是荒謬的。這是一個艱難的教訓。

這被稱爲SELECT N + 1問題。 1爲父實體,N爲正被加載的關聯實體的數量。你會希望L2S能夠足夠聰明,並且可以在一個巨大的查詢中得到它,但不幸的是並非如此。它會創建一個巨大的查詢,告訴它要加載的關聯的ID,然後逐個檢索這些關聯。

也許最好的解決方法是使用投影,以便您的LINQ查詢返回一個新對象,而不是一個實體。例如:

var fooDtos = from foo in db.Foo 
       where foo.bar == "What a great example" 
       select new fooDTO { FooName = foo.Name, FooBar = foo.Bar }; 

該查詢返回一個IEnumerable < FooDTO>代替的IQueryable <美孚>。這有兩個好處。首先你要指定L2S專門檢索哪些列,所以它不會執行SELECT *。此外,您不再需要DataLoadOptions,因爲您可以在查詢中查詢您想要的任何表並從任何表中選擇以生成DTO。