具有多个左外连接的 SQL 到 Linq 查询

本文关键字:SQL Linq 查询 连接 | 更新日期: 2023-09-27 18:33:20

我正在尝试将SQL query转换为包含多个左外连接的Linq,但我遇到了一个奇怪的情况。

我的SQL的相关部分是:

SELECT * FROM dbo.SessionDetails as sd
    left outer join dbo.VoipDetails as vd on vd.SessionIdTime = sd.SessionIdTime and vd.SessionIdSeq = sd.SessionIdSeq
    left outer join dbo.Gateways as fgw on vd.FromGatewayId = fgw.GatewayId

到目前为止,我的 Linq 查询是:

var query = from sd in dbo.SessionDetails
    join vd in dbo.VoipDetails on new { sd.SessionIdTime, sd.SessionIdSeq } equals new { vd.SessionIdTime, vd.SessionIdSeq } into sdvd
    from v in sdvd.DefaultIfEmpty()
         join fgw  in dbo.Gateways on vd.FromGatewayId equals fgw.GatewayId   into sdgw
         from g in sdvd.DefaultIfEmpty()
             select sd;

我在告诉我vd.FromGatewayId时收到一个错误标记The name 'vd' is not in scope on the left side of 'equals'. Consider swapping the expressions on either side of 'equals'.
但是,如果我确实与gw.GatewayId交换了一边,那么我会收到相同的错误消息,vdgw。有人可以在这里建议正确的语法吗?请记住,在我掌握基本语法后,我还需要添加几个左连接。

具有多个左外连接的 SQL 到 Linq 查询

我相信问题是您正在尝试访问查询中没有范围的值。 我相信这样做的原因是您指定了关系船,然后将这些值分配给名为 sdvd 的集合,此时您无法访问 vd。 也就是说,您然后通过这样做来执行from v in sdvd.DefaultIfEmpty(),这样您就可以访问 sdvd 中的行,这些行与您认为vd持有的值相同。 您应该能够使用 v 而不是 vd . 我不得不模拟一些东西来测试,所以我无法完全测试这个查询,但以下内容应该运行。

var query = from sd in dbo.SessionDetails
    join vd in dbo.VoipDetails on new { sd.SessionIdTime, sd.SessionIdSeq } equals new { vd.SessionIdTime, vd.SessionIdSeq } into sdvd
    from v in sdvd.DefaultIfEmpty()
        join fgw  in dbo.Gateways on v.FromGatewayId equals fgw.GatewayId   into sdgw
        from g in sdvd.DefaultIfEmpty()
            select sd;

编辑 2014/12/08

为了了解 linq 语句如何转换为 sql,我建议您安装 https://www.linqpad.net/。 您可以在那里设置连接并测试查询,并在结果视图中查看 sql。

由于我没有这个问题的数据结构,这将很难。说我模拟了一些东西:

from sd in  Employees
    join vd in TimeEntries on new { sd.EmployeeID } equals new { vd.EmployeeID } into sdvd
    from v in sdvd.DefaultIfEmpty()
        join fgw  in EmployeeGroupDetails on v.EmployeeID equals fgw.EmployeeID   into sdgw
        from g in sdgw.DefaultIfEmpty()
            select  sd

这会产生:

SELECT [t0].*
FROM [Employee] AS [t0]
LEFT OUTER JOIN [TimeEntry] AS [t1] ON [t0].[EmployeeID] = [t1].[EmployeeID]
LEFT OUTER JOIN [EmployeeGroupDetail] AS [t2] ON [t1].[EmployeeID] = [t2].[EmployeeID]

它确实返回了正确的连接。