2013-08-21 55 views
0

對於LINQ和lambda表達式,我有點新手,我希望有人能幫助我。如何查詢匹配實體列表中的所有子對象?

我在做什麼是創建一個ADO.NET SqlDataReader與響應中的多個數據'表'的聚合對象。

記錄集是這樣的:


FooId
...其他描述性領域

酒吧
BarId
FooId
...其他描述性領域

巴茲
BazId
BarId
...其他描述性領域

我迭代通過每個數據表,一次一個。在處理好第一張桌子後,我擁有了所有的「Foos」,然後第二個是「Bars」,我可以毫不費力地將它與「Foo」相關聯。 (一個「酒吧」可以分配給多個Foo)。

我保溼目的是列表(通過Web服務返回它的目的)和物體看起來像這樣(僞):

class Foo 
{ 
    int FooId 
    string Name 
    string etc 
    string YouGetTheIdea 
    List<Bar> Bars 
} 

class Bar 
{ 
    int BarId 
    string etc 
    List<Baz> Bazes 
} 

class Baz 
{ 
    int BazId 
    string etc 
} 

到現在爲止,我沒事。我遇到麻煩的地方在於,「酒吧」對象具有可以附加到多於一個「酒吧」(其可以連接到多於一個「Foo」)的「Baz」對象的列表

到目前爲止,我的代碼看起來像這樣。如果有更好的方法來解決這個問題,請告訴我。 我的麻煩是,當我到達處理「Baz」的部分時,我不知道如何選擇所有「Bar」對象(在任何具有該Id的Bar的Foo下),以便可以將當前的BazId添加到它的Baz對象列表。我現在在這裏有什麼在運行時爆炸,所以它顯然是不正確的。

using (SafeDataReader reader = this.ExecSPReader(SP_NAME, parms.ToArray())) 
{ 
    if (reader != null) 
    { 
     // deal with Foos 
     while (reader.Read()) 
     { 
      Foo o = new Foo(); 
      o.FooID = reader.GetInt64("FooID"); 
      o.Etc = reader.GetString("etc"); 
      //...more properties 
      fooList.Add(o); 
     } 

     // deal with Bars 
     reader.NextResult(); 
     while (reader.Read()) 
     { 
      Bar p = new Bar(); 
      long BarFooID = reader.GetInt64("FooID"); 

      p.BarID = reader.GetInt64("BarID"); 
      //...more properties 

      // find Foo that has this Bar and add to it 
      Foo o = fooList.Find(x => x.FooID == barFooID); 
      if (o != null) 
      { 
       if (o.Bars == null) 
       { 
        o.Bars = new List<Bar>(); 
       } 
       o.Bars.Add(p); 
      } 
     } 
/* 
*** 
*** Up to here, everything is fine 
*** ...but now we need to assign the baz elements to bars, which can belong 
***  to any/all Foos 
*** 
*/ 
     // deal with Bazs 
     reader.NextResult(); 
     while (reader.Read()) 
     { 
      long bazID = reader.GetInt64("BazID"); 
      long barID = reader.GetInt64("BarID"); 

      // here is the problem, ideally I'd like to get a list of all Bar elements with 
      // the BarID from the datarow, but not sure how to do that -- the below foreach 
      // line errors at runtime 
      foreach(Bar p in fooList.Select(a => a.Bars.Where(b => b.BarID == barID))) 
      { 
       if (p.Bazes == null) 
       { 
        p.Bazes = new List<Baz>(); 
       } 
       p.Bazes.Add(bazID); 
      } 
     } 
    } 
} 

非常感謝任何幫助。

+0

_這可以附加到多個「欄」_ - 不與給定的表定義。確保你明確了1對N和N對M的關係,然後放棄並使用實體框架。 –

+0

@HenkHolterman爲什麼不能附加到多個酒吧? –

+0

@HenkHolterman - 這些不是表格,它們是查詢輸出。你是正確的,如果它是表def,那將是一個1-1關係,但是給定的BazId有多行。 :) – Cortright

回答

2

使用SelectMany (MSDN)

foreach(Bar p in fooList.SelectMany(a => a.Bars.Where(b => b.BarID == barID))) 
      { 
       if (p.Bazes == null) 
       { 
        p.Bazes = new List<Baz>(); 
       } 
       p.Bazes.Add(bazID); 
      } 

更新爲a.Bars可能爲空;

foreach(Bar p in fooList.Where(a => a.Bars !=null).SelectMany(a => a.Bars.Where(b => b.BarID == barID))) 
      { 
       if (p.Bazes == null) 
       { 
        p.Bazes = new List<Baz>(); 
       } 
       p.Bazes.Add(bazID); 
      } 
+0

鮑勃 - 這是完美的,似乎正是我想要的。不敢相信我離得太近了!也感謝有關空檢查的更新。我也把它放在裏面。 – Cortright

相關問題