帮助这个Linq查询(多对多连接)

时间:2011-03-04 17:38:55

标签: c# 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的方法是什么?

2 个答案:

答案 0 :(得分: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序列。

这可以通过“索引”子类课程地图进行有效查找来改进,如下所示:

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();

答案 1 :(得分: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();
相关问题