我有一个需要在gridview中显示的TimeTable的以下数据集。目前,数据集的片段如下所示:
SessionNum TimeStart TimeStop Details
---------- --------- -------- -------
1 08:00 09:00 Math101
1 09:00 10:00 Comp102
1 11:00 12:00 Engn101
2 08:00 09:00 Comp102
2 09:00 10:00 Math101
2 10:00 11:00 Acco103
总共有5个会话,我希望数据集看起来像:
TimeStart TimeStop Session1 Session2 ...
--------- -------- -------- -------- ---
08:00 09:00 Math101 Comp102
09:00 10:00 Comp102 Math101
10:00 11:00 - Acco103
11:00 12:00 Engn101 -
正如您将看到的,不需要集合功能......只是分组,但对于我的生活,我似乎无法绕过这一个。我有以下LINQ查询生成第一个数据集:
List<TimeTable> list = db.TimeTables.OrderBy(o => o.TimeStart).OrderBy(o => o.SessionNum).ToList();
这很好用,并生成按SessionNum
然后TimeStart
排序的数据集。我解决这个问题的尝试引发了以下问题:
var result = list.GroupBy(t => t.TimeStart).Select(s => new {
TimeStart = s.Key,
Session1 = s.Where(x => x.SessionNum == 1),
Session2 = s.Where(x => x.SessionNum == 2)
});
这跑了,但遗憾的是没有用。我知道需要一个GroupBy
(或一对),但从这一点开始我有点迷失。我真的很感激任何帮助解决这个问题。提前谢谢!
答案 0 :(得分:5)
您无法在LINQ中直接执行数据透视查询。你可以做的是创建一个这样的结构:
var record = new
{
TimeStart = "10:00",
TimeStop = "11:00",
Sessions = new [] { "-", "Acco103", },
};
如果有这些记录的列表,则必须确保Sessions
属性的数组长度与整个数据集中的不同会话数相同。然后,您可以通过索引到数组来访问会话信息。
在查看查询后,这应该更有意义。
首先,在数据库中查询所需数据:
var query =
from s in db.TimeTables
orderby s.TimeStop
orderby s.TimeStart
group s by new { s.TimeStart, s.TimeStop } into gss
select new
{
gss.Key.TimeStart,
gss.Key.TimeStop,
Sessions = gss.ToArray(),
};
现在确定不同的会话集:
var sessionNums =
db.TimeTables
.Select(s => s.SessionNum)
.Distinct()
.OrderBy(n => n)
.ToArray();
现在在内存中处理此数据(请注意.ToArray()
上的query
调用):
var process =
from q in query.ToArray()
let lookup = q.Sessions
.ToLookup(s => s.SessionNum, s => s.Details)
select new
{
q.TimeStart,
q.TimeStop,
Sessions = sessionNums
.Select(n => String.Join(
", ",
lookup[n].DefaultIfEmpty("-")))
.ToArray(),
};
这是艰苦的工作。 lookup
创建了一种简单的方法来获取任何SessionNum
的会话详细信息。调用lookup[n].DefaultIfEmpty("-")
可确保每个会话至少有一个值。 String.Join
确保如果源数据同时具有同一会话号的两个会话,那么我们最终会得到一个值。
无论有多少会话,这个结果都是安全的,因为它只会扩展数组。
process
查询的输出如下所示:
然后你可以做这个查询:
var result =
from p in process
select new
{
p.TimeStart,
p.TimeStop,
Session1 = p.Sessions[0],
Session2 = p.Sessions[1],
};
这将有效地“转动”您的结果,但您需要明确地输入每个“SessionX”属性。
result
查询的输出如下所示: