2012-11-24 29 views
1

我的菜單項列表中的數據庫,如:如何創建最佳查詢?

ID  ParentID  ItemOrder  Name 
-------------------------------------------------------  
1  null    1  Main_1 
2  null    2  Main_2 
3  null    3  Main_3 
4  null    4  Main_4 
5  null    5  Main_5 
6  1     4  SubMenu_1.4 
7  1     5  SubMenu_1.5 
8  1     8  SubMenu_1.8 
9  2     1  SubMenu_2.1 
10  3     1  SubMenu_3.1 
11  3     2  SubMenu_3.2 
12  3     4  SubMenu_3.4 

Submenu ItemOrder在1不一定啓動,其可能與3開頭,下面的菜單項順序可以是7等。

如何創建將返回所有父級(零級)菜單項及其第一個子項(如果存在)的linq查詢或lambda表達式?

預期的結果:

ID  ParentID  ItemOrder  Name 
-------------------------------------------------  
1  null    1   Main_1 
2  null    2   Main_2 
3  null    3   Main_3 
4  null    4   Main_4 
5  null    5   Main_5 
6  1    4   SubMenu_1.4 
9  2    1   SubMenu_2.1 
10  3    1   SubMenu_3.1 
+0

歡迎使用StackOverflow:如果您發佈代碼,XML或數據樣本,請**在文本編輯器中突出顯示這些行,然後單擊編輯器工具欄上的「代碼示例」按鈕(「{}」)格式和語法突出顯示它!這樣,你就不再需要那些真的很雜亂的' '和'
'標籤了! –

回答

1
var items = dbContext.Table 
    .Where(item => item.ParentID == null) 
    .Union(dbContext.Table 
     .Where(x => x.ParentID != null) 
     .GroupBy(x => x.ParentID) 
     .Select(g => g.FirstOrDefault())); 
+1

這個答案是正確的,但我認爲你需要使用FirstOrDefault而不是第一個 – MVCKarl

+0

@MVCKarl,沒有必要使用'FirstOrDefault' - 如果沒有項目,比方說'ParentID == 3',那麼將不會有帶'Key == 3'組。換句話說,每個組都至少有一個元素。 – RePierre

+0

由於使用First而不是FirstOrDefault,這給了我'NotSupportedException'。還有一個缺失的支架。我認爲這些值不是按要求排序的。 –

0
public IQueryable<MenuItem> MakeQuery() 
{ 

    var parentsQuery = 
     from parent in ctx.MenuItem 
     where parent.ParentID == null 
     orderby parent.ItemOrder 
     select parent; 

    var childrenQuery = 
     from parent in parentsQuery 
     join child in ctx.MenuItem 
      on parent.ID equals child.ParentID 
     where !ctx.MenuItem.Any(child2 => child2.ParentID == parent.ID 
      && child2.ItemOrder < child.ItemOrder) 
     orderby child.ItemOrder 
     select child; 

    return parentsQuery.Concat(childrenQuery); 
} 

這就避免了錯誤 「在歐盟或Concat的類型是不兼容的構建。」從LINQ到SQL,只會返回一級子級。

+0

我覺得你的答案更好,因爲有直接鏈接到父母。我會稍後嘗試你的版本。 – wakeup

0

我會用這個查詢

var parents = table.Where(i => i.ParentID == null); 
    var immediateChildren = table 
     .GroupBy(i => i.ParentID) 
     .Select(g => g.OrderBy(i => i.ItemOrder).FirstOrDefault()); 
    var result = parents.Union(immediateChildren); 

結果只包括直接孩子的要求和變量有助於瞭解發生了什麼事情。

+0

也不錯,會試試你的樣品),謝謝! – wakeup

+0

這是我在stackoverflow上的第一個問題。感謝所有迴應的人。 RePierre首先回答,但我認爲Markus Jarderot的答案更正確。我在linq中不擅長,所以我會嘗試使用所有版本並測試它們的性能。 – wakeup