LINQ:自连接查询,如何实现?
有人能帮忙吗 我有一个类,基本上它包含成员,在这个类中有一个列表 我名单上的成员也。。。所以基本上是这样的 我有2名成员,每个成员有若干次会议 我只想让每位成员参加一次会议 我已经做了一个LINQ查询,但它当然不起作用 我想我需要做一个自我连接,有什么想法吗 基本上我的错误是我的子查询自连接中不存在mLINQ:自连接查询,如何实现?,linq,linq-to-sql,linq-to-objects,self-join,Linq,Linq To Sql,Linq To Objects,Self Join,有人能帮忙吗 我有一个类,基本上它包含成员,在这个类中有一个列表 我名单上的成员也。。。所以基本上是这样的 我有2名成员,每个成员有若干次会议 我只想让每位成员参加一次会议 我已经做了一个LINQ查询,但它当然不起作用 我想我需要做一个自我连接,有什么想法吗 基本上我的错误是我的子查询自连接中不存在m var sessions = from m in this.members join s in ( from se in m.Sessions
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的最佳方式吗
谢谢。除非我遗漏了什么你需要这个,不是吗
var sessions =
from m in members
select new {
MemberName = m.Name,
SessionTime = m.Sessions.Max(s => s.SessioEndTime)
};
您必须改变思考LINQ查询的方式,更多地从对象的角度而不是从SQL实现的角度来思考。我需要什么?我需要所有成员,每个成员都有其最新的会议结束时间,然后采取行动
编辑:
您使用的let选项是可以的,请记住,如果成员的会话列表为空,则FirstOrDefault
将返回null,然后sn.sessionedTime将命中null引用。另一方面,如果您确定每个成员至少有一个会话,请先使用或聚合。
另外,不要在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};
对于ordering vs Max aggregation,两个查询都将生成一个子查询:
-- 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]
如果SessionEndTime上有一个降序索引,则排序脚本的速度大约慢两倍(您可以自己检查这些脚本的执行计划),如果没有索引,则速度大约慢五倍。是的,谢谢,让我们看看我是否正确,我使用了“let”,这样可以吗?还是有更好的办法?现在我让sn=m.Sessions.OrderByDescending(a=>a.SessionEndTime).FirstOrDefault(),现在我有了会话的完整记录,所以我可以执行sessiontime=sn.SessionEndTime以及其他属性。。