有人可以帮忙吗?
我有1个类,基本上它拥有成员,并且在该类中是List。
我在列表中的成员也......所以基本上就是这样,
我有2名成员,每名成员都有多个会议。
我希望只返回每个成员一次。
我已经完成了LINQ查询,但当然它不起作用......
我想我需要自我加入,任何想法?
基本上我的错误是m在我的子查询自连接中不存在。
var sessions =
from m in this.members
join s in
(
from se in m.Sessions
group se by se.Name into g
select new {Name = g.Key, SessioEndTime = g.Max(a=>a.SessioEndTime)}
)
on m.Name equals s.Name
select new { MemberName = m.Name, SessionTime = s.SessioEndTime}
我很感激任何人的反馈。
提前致谢。
修改
好的,我设法做到如下,但这是最好的方法吗?
var sessions =
from m in this.members
let sn = m.Sessions.OrderByDescending(a => a.SessionEndTime).FirstOrDefault()
select new { MemberName = m.Name, SessionTime = sn.SessioEndTime}
这样sn包含1条记录,但我可以访问所有属性......
但这是使用LET的最佳方法吗?
感谢。
答案 0 :(得分:5)
除非我遗漏了你需要的东西,否则没有?
var sessions =
from m in members
select new {
MemberName = m.Name,
SessionTime = m.Sessions.Max(s => s.SessioEndTime)
};
您必须改变您对LINQ查询的看法,从对象点而不是从SQL实现点考虑更多。我需要什么?我需要所有成员,每个成员都有最新的会话结束时间,然后采取行动。
修改强>
您使用的let选项没问题,只需记住一些事项FirstOrDefault
如果成员有一个空的Sessions列表,则返回null,然后sn.SessionEndTime命中null引用。另一方面,如果您确定每个成员至少有一个会话使用First
代替或聚合。
同样不要在let中使用FirstOrDefault()
,这会弄乱LINQ并阻止它将它绑定到主服务器(导致每个主服务器单独的SQL查询检测丢失的子集),所以可以使用let查询是:
from m in Members
let sn = m.Sessions.Max(s => s.SessioEndTime)
select new { MemberName = m.Name, SessionTime = sn};
from m in Members
let sn = m.Sessions.OrderByDescending(a => a.SessioEndTime).First()
select new { MemberName = m.Name, SessionTime = sn.SessioEndTime};
对于排序与Max聚合,两个查询都将生成子查询:
-- MAX
SELECT [t0].[Name] AS [MemberName], (
SELECT MAX([t1].[SessioEndTime])
FROM [Session] AS [t1]
WHERE [t1].[memberId] = [t0].[id]
) AS [SessionTime]
FROM [Member] AS [t0]
GO
-- ordering
SELECT [t0].[Name] AS [MemberName], (
SELECT [t2].[SessioEndTime]
FROM (
SELECT TOP (1) [t1].[SessioEndTime]
FROM [Session] AS [t1]
WHERE [t1].[memberId] = [t0].[id]
ORDER BY [t1].[SessioEndTime] DESC
) AS [t2]
) AS [SessionTime]
FROM [Member] AS [t0]
在SessioEndTime上使用降序索引时,排序脚本的速度大约慢两倍(您可以获得执行计划以自行检查),而索引的速度大约慢5倍。