Linq分组问题

时间:2011-09-12 12:12:42

标签: linq entity-framework linq-to-entities

我正在为会议室制作一个简单的预订系统。每个会议室都根据房间大小等分配房型。我希望从以下方面确定预订房间的数量:

01/01/2011  1   Room A  2
01/01/2011  2   Room B  5
01/01/2011  3   Room C  3
01/01/2011  4   Room D  2
01/01/2011  5   Room E  1
01/01/2011  6   Room F  5
02/01/2011  1   Room A  3
02/01/2011  2   Room B  5
02/01/2011  3   Room C  2
02/01/2011  4   Room D  5
02/01/2011  5   Room E  2
02/01/2011  6   Room F  2
03/01/2011  1   Room A  2
03/01/2011  2   Room B  5
03/01/2011  3   Room C  2

分组数据,例如:

Date        Room A  Room B  Room C  Room D  Room E  Room F
01/01/2011  2       5       3       2       1       5
02/01/2011  3       5       2       5       2       2
03/01/2011  2       5       2       4       5       8
04/01/2011  4       7       3       5       2       2

我之前已经设法使用数据集,但我需要能够在Linq中使用Linq来实现此项目

有人可以建议最好的方法吗?

由于

1 个答案:

答案 0 :(得分:0)

这是我在面对这类问题时所做的事情:

var rooms = bookings
    .Select(b => b.Room)
    .Distinct()
    .OrderBy(r => r)
    .ToArray();

var query = (
    from b in bookings
    group b by b.Date into gbs
    let l = gbs.ToLookup(gb => gb.Room, gb => gb.Count)
    select new
    {
        Date = gbs.Key,
        RoomCounts = rooms.Select(r => l[r].Sum()).ToArray(),
    }).ToArray();

这实际上产生了以下数组:

var rooms = new []
{
    "Room A", "Room B", "Room C", "Room D", "Room E", "Room F",
};

var query = new []
{
    new
    {
        Date = new DateTime(2011, 01, 01),
        RoomCounts = new [] { 2, 5, 3, 2, 1, 5 }
    },
    new
    {
        Date = new DateTime(2011, 01, 02),
        RoomCounts = new [] { 3, 5, 2, 5, 2, 2 }
    },
    new
    {
        Date = new DateTime(2011, 01, 03),
        RoomCounts = new [] { 2, 5, 2, 0, 0, 0 }
    },
};

RoomCounts数组的长度与rooms数组的长度相同,每个索引位置的值与rooms数组中的空间匹配。

这通常是相当可行的。

另一种方法是创建一个数组数组,表示网格有点像电子表格。

var query2 = (new object[]
    {
        (new object[] { "Date" })
            .Concat(rooms.Cast<object>())
            .ToArray()
    }).Concat(
        from b in bookings
        group b by b.Date into gbs
        let l = gbs.ToLookup(gb => gb.Room, gb => gb.Count)
        select (new object[] { gbs.Key })
            .Concat(rooms.Select(r => l[r].Sum()).Cast<object>())
            .ToArray())
            .ToArray();

这会产生以下结果:

    var q2 = new object[]
    {
        new object[] {
            "Date", "Room A", "Room B", "Room C", "Room D", "Room E", "Room F" },
        new object[] { new DateTime(2011, 01, 01), 2, 5, 3, 2, 1, 5 },
        new object[] { new DateTime(2011, 01, 02), 3, 5, 2, 5, 2, 2 },
        new object[] { new DateTime(2011, 01, 03), 2, 5, 2, 0, 0, 0 },
    };

如果查询看起来有点毛茸茸,另一种替代方法是执行此操作:

Func<object, IEnumerable, object[]> prepend = (o, os) =>
    (new object[] { o }).Concat(os.Cast<object>()).ToArray();

Func<object[], IEnumerable<object[]>, object[][]> prepends = (o, os) =>
    (new object[][] { o }).Concat(os).ToArray();

var query2 = prepends(prepend("Date", rooms),
    from b in bookings
    group b by b.Date into gbs
    let l = gbs.ToLookup(gb => gb.Room, gb => gb.Count)
    select prepend(gbs.Key, rooms.Select(r => l[r].Sum())));

这种形式的查询仍然会产生相同的对象网格,但它比第一种形式更具可读性,恕我直言。

我希望这会有所帮助。