如何用中间表进行Linq左外部联接?

时间:2018-12-10 04:29:08

标签: c# linq join

我一直在关注此网站上的一些示例,以了解如何创建Linq左外连接查询,但是我还没有找到“左连接中的外键未指向内键”的示例。而是指向上一个键”。请接受我的说法,我知道这是不正确的,但请看以下代码片段,也许会更清楚。

具体来说,请参见第一个左连接,其中sp.SalesPersonID = j.SalesPersonID。

select rt.Name as ResourceType, s.FirstName + ' ' + s.Surname as Supervisor, sp.FirstName + ' ' + sp.LastName as SalesPerson, tr.OrderCodeID, tr.SkillID
    , j.CustomerName, j.JobNumber
from dbo.TaskResource tr join projects.Task t on t.ID = tr.taskiD
    join dbo.ResourceType rt on rt.ID = tr.ResourceTypeID
    join projects.projecttask pt on pt.taskid = tr.taskid 
    join projects.jobproject jp on jp.projectid = pt.projectid 
    join crm.tbljobs j on j.jobid = jp.jobid 
    left join common.tblSalesPersons sp on sp.SalesPersonID = j.SalesPersonID
    left join common.tblSupervisors s on s.SupervisorID = j.SupervisorID
where JobDeleted is null or JobDeleted = 0
order by ResourceType

转换为Linq后,它会变成

...from j in temp1.DefaultIfEmpty()
    join sp in dbc.tblSalesPersons on j.SalesPersonID equals sp.SalesPersonID into temp2

到目前为止,一切都很好。但是,当我进行下一个左联接时,虽然会是一样的事情,但是正如我前面提到的,指向先前的键之一,所以不要使用 sp 变量我已经看过几个示例,我使用的是来自先前联接的 j 变量:

from sp in temp2.DefaultIfEmpty()
    join s in dbc.tblSupervisors on j.SupervisorID equals s.SupervisorID

这是完整的代码段:

List<ResourceTreeObject> resourceTreeObjects = (
                from tr in dbc.TaskResources
                join t in dbc.Tasks on tr.TaskID equals t.ID
                join rt in dbc.ResourceTypes on tr.ResourceTypeID equals rt.ID
                join pt in dbc.ProjectTasks on tr.TaskID equals pt.TaskID
                join jp in dbc.JobProjects on pt.ProjectID equals jp.ProjectID
                join j in dbc.tblJobs on jp.JobID equals j.JobID into temp1
                from j in temp1.DefaultIfEmpty()
                join sp in dbc.tblSalesPersons on j.SalesPersonID equals sp.SalesPersonID into temp2
                from sp in temp2.DefaultIfEmpty()
                join s in dbc.tblSupervisors on j.SupervisorID equals s.SupervisorID
                where j.JobDeleted == null || j.JobDeleted == 0
                select new ResourceTreeObject
                {
                    TaskResourceID = tr.ID
                    ,
                    TaskID = tr.TaskID
                    ,
                    ResourceTypeID = tr.ResourceTypeID
                    ,
                    ResourceType = rt.Name
                    ,
                    SkillID = tr.SkillID
                    ,
                    OrderCodeID = tr.OrderCodeID
                    ,
                    PermissionID = tr.PermissionID
                    ,
                    JobID = j.JobID
                    ,
                    JobNumber = j.JobNumber
                    ,
                    CustomerName = j.CustomerName
                    ,
                    Salesperson = sp.FirstName + " "  + sp.LastName
                    ,
                    Supervisor = s.FirstName + " " + s.Surname

                }).ToList();

这将导致错误的查询。最后一个“左连接”被视为内部连接,并返回错误的行数。因此,从本质上讲,我要问的是,在执行几次连续的内部联接之后,如何(在LinQ中)执行两个连续的左外部联接,但如何使用我的左联接中先前表之一的键?

我也不确定内/外键等的正确术语,因此措辞和标题很尴尬。也许有人可以纠正它,这样对他人会更有利。谢谢。

1 个答案:

答案 0 :(得分:1)

您的LINQ翻译才刚刚结束。

SQL在crm.tbljobs上具有内部联接,然后在common.tblSalesPersoncommon.tblSupervisors上具有外部联接。

LINQ在dbc.tblJobsdbc.tblSalesPersons上具有外部联接,随后在dbc.tblSupervisors上具有内部联接。

into temp1 ... from j in in temp1.DefaultIfEmpty()使外部联接发生在into之前引入的表dbc.tblJobs上。

应该是:

...
// inner join
join j in dbc.tblJobs on jp.JobID equals j.JobID

// left outer join
join sp in dbc.tblSalesPersons on j.SalesPersonID equals sp.SalesPersonID into salesPersons
from sp in salesPersons.DefaultIfEmpty()

// left outer join
join s in dbc.tblSupervisors on j.SupervisorID equals s.SupervisorID into supervisors
from s in supervisors.DefaultIfEmpty()
...

我将temp1temp2更改为更有意义的名称,以演示它们在外部联接语法中所代表的含义。请注意,例如dbc.tblSalesPersonssalesPersons的关系和相对位置。

要记住的另一件事是sps可以为null,因此请确保在访问它们的FirstNameLastName和{{ 1}}属性。