2011-03-04 56 views
1

我有三個域對象:幫助此Linq查詢(多對多連接)

兒童,課堂和兒童房間。這裏是每一個列表:

var childrens = new List<Child>() { 
    new Child() { ChildId = 1, FirstName = "Chris" }, 
    new Child() { ChildId = 2, FirstName = "Jenny" }, 
    new Child() { ChildId = 3, FirstName = "Dave" }, 
}; 

var classrooms = new List<Classroom>() { 
    new Classroom() { ClassroomId = 1, FullName = "Kindergarten" }, 
    new Classroom() { ClassroomId = 2, FullName = "Elementary" }, 
    new Classroom() { ClassroomId = 3, FullName = "Secondary" }, 
}; 

var childclassrooms = new List<ChildClassroom>() { 
    new ChildClassroom() { ClassroomId = 1, ChildId = 1 }, 
    new ChildClassroom() { ClassroomId = 2, ChildId = 1 }, 
    new ChildClassroom() { ClassroomId = 3, ChildId = 2 }, 
}; 

我要的是:

var childClassroomRelationships = new object[] { 
    new { 
     childid = 1, 
     classrooms = new object[] { 
      new { classroomId = 1, occupied = true }, 
      new { classroomId = 2, occupied = true }, 
      new { classroomId = 3, occupied = false } 
    }, 
    ... 
}; 

什麼去這Linq中的方法是什麼?

+10

我開始更好地進行格式化。 – 2011-03-04 17:40:53

+1

如果不使用類型推斷('new [] {...}'')創建數組,則可以訪問匿名類型的成員:'childClassroomRelationships [0] .childid'。如果你將它創建爲'new object []',那麼你將無法使用匿名類型做很多事情,而不需要一些巫術。 – 2011-03-04 17:48:49

+0

@ Yuriy-完成。現在你應該能夠回答。 – 2011-03-04 17:49:01

回答

2
var kidsInClass = (
    from kid in childrens 
    from c in classrooms 
    select new { 
     ChildID = kid.ChildId, 
     classrooms = (
      from cc in childclassrooms 
      select new { 
       ClassroomID = c.ClassroomId, 
       Occupied = cc.ChildId == kid.ChildId 
      }).ToArray() 
    }).ToArray(); 
+1

@casperOne我不認爲需要格式編輯,但也許這就是我。 – 2011-03-04 18:35:09

+0

@Yuriy:謝謝你對這個問題的所有幫助。 – 2011-03-04 20:47:59

+0

@Chris隨時。 – 2011-03-04 20:56:20

3

你可以這樣做:

var childClassroomRelationships = (
    from child in children 
    select { 
     childid = child.ChildId, 
     classrooms = (
      from classroom in classrooms 
      select new { 
       classroomId = classroom.ClassroomId, 
       occupied = childclassrooms.Any(
        cc => cc.ChildId == child.ChildId), 
      // Since you wanted an array. 
      }).ToArray() 
    // Since you wanted an array. 
    }).ToArray(); 

什麼是這裏非常重要的是,一個連接應該用在這裏,如果是,你會得到內部聯接語義,這將導致孩子誰不在任何教室沒有出現(這似乎你不要希望從你給的例子)。

請注意,由於對ToArray的調用,這將實現所有序列。

此外,它的效率稍低,因爲要檢查佔用情況,每次都必須重複整個childclassroms序列。

這可以通過「索引」的childclassrooms地圖進行有效的查找,像這樣進行改進:

IDictionary<int, HashSet<int>> classroommap = (
    from mapping in childclassrooms 
    group mapping.ClassroomId by mapping.ChildId into g 
    select g).ToDictionary(g => g.Key, g => new HashSet<int>(g)); 

這會給你的地圖HashSet<int>實例的,你可以看一下孩子,一旦你知道了課堂。就這樣,第一個查詢變爲:

var childClassroomRelationships = (
    from child in children 
    select { 
     childid = child.ChildId, 
     classrooms = (
      from classroom in classrooms 
      select new { 
       classroomId = classroom.ClassroomId, 
       occupied = classroommap.ContainsKey(child.ChildId) && 
        classroommap[child.ChildId]. 
         Contains(classroom.ClassroomId), 
      // Since you wanted an array. 
      }).ToArray() 
    // Since you wanted an array. 
    }).ToArray();