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

时间:2014-12-07 09:44:29

标签: c# linq entity-framework join entity-framework-4

我试图将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收到相同的错误消息。 有人可以在这里建议正确的语法吗? 请记住,在我获得基本语法后,我还要添加几个左连接。

1 个答案:

答案 0 :(得分:2)

我认为问题在于您正在尝试访问查询中没有作用域的值。我认为这样做的原因是你指定了关系,然后将这些值分配给一个名为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;

EDIT 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

这个YIELDS:

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]

它确实以合适的连接回来。