Как сделать левое внешнее соединение Linq со средней таблицей? - PullRequest
0 голосов
/ 10 декабря 2018

Я следил за несколькими примерами с этого сайта о том, как создавать запросы Linq Left Outer Join, но я не нашел примеров того, как «внешний ключ в левом соединении не указывает на внутренний ключ, новместо этого указывает на предыдущий ключ ".Терпите меня за эту фразу, я знаю, что это не правильно, но взгляните на следующие фрагменты кода, и, возможно, это будет яснее.

В частности, см. Первое соединение слева, где 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 голосов
/ 10 декабря 2018

Ваш перевод LINQ немного отклонен.

SQL имеет внутреннее соединение на crm.tbljobs, за которым следуют внешние соединения на common.tblSalesPerson и common.tblSupervisors.

LINQ имеетвнешние соединения в dbc.tblJobs и dbc.tblSalesPersons, за которыми следует внутреннее соединение в dbc.tblSupervisors.

into temp1 ... from j in in temp1.DefaultIfEmpty() делает возможным внешнее соединение в таблице, введенной до intodbc.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()
...

Я изменил temp1 и temp2 на более значимые имена, чтобы продемонстрировать, что они представляют в синтаксисе внешнего соединения,Обратите внимание, например, на отношение и относительное положение от dbc.tblSalesPersons до salesPersons.

Еще одна вещь, которую нужно помнить, это то, что sp и s могут быть нулевыми, поэтому убедитесь, что вы проверили это переддоступ к их FirstName, LastName и Surname свойствам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...