Преобразование левого внешнего присоединения к структуре сущности
-
14-11-2019 - |
Вопрос
Вот запрос SQL, который я хочу преобразовать в EF4.3
command = database.GetSqlStringCommand(@"
select
H.AUTHENTICATION_ID,
USERNAME,
PERMISSIONS,
ORGANIZATION_IDENTIFIER,
O.ORGANIZATION_ID
from
AUTHENTICATION H
left join [AUTHORIZATION] T on H.AUTHENTICATION_ID=T.AUTHENTICATION_ID
join ORGANIZATION O on O.ORGANIZATION_ID = T.ORGANIZATION_ID
order by H.AUTHENTICATION_ID");
.
Вот лучший linq, который я мог бы придумать:
var query = from h in context.Authentications
join t in context.Authorizations on h.AuthenticationId equals t.Authentications.AuthenticationId
join o in context.Organizations on t.Organizations.OrganizationId equals o.OrganizationId
orderby
h.AuthenticationId
select new
{ AUTHENTICATION_ID = (Int16?)h.AuthenticationId,
h.Username,
t.Permissions,
o.OrganizationIdentifier,
OrganizationID = (Int16?)o.OrganizationId
};
.
Я знаю, что мне нужно объединить мой первый присоединение (между авторизациями и аутентификациями), позволяет сказать x и применить defalfulty, но не может разглядеть синтаксис.
<Сильные> Редактировать: Изображение для разъяснения:
Любая помощь будет высоко оценена.С уважением.
Решение
Базовый синтаксис для «левого присоединения» в LINQ подобно следующему:
from x in table1
join y in table2 on x.id equals y.id into jointable
from z in jointable.DefaultIfEmpty()
select new
{
x.Field1,
x.Field2,
x.Field3,
Field4 = z == null ? 0 : z.Field4
};
.
В вашем случае я немного запутался, потому что отношения сущности, которые вы, кажется, используете в вашем LINQ, не соответствуют тем, что подразумевается вашим SQL;Здесь отношения здесь нулевой или один, нулевой или много, один к одному и т. Д.?В частности, вы делаете это:
from h in context.Authentications
join t in context.Authorizations on h.AuthenticationId equals t.Authentications.AuthenticationId
.
Но ваш SQL подразумевает, что «аутентификация» является родительским здесь с нолью или более «авторизацией» детьми, а не наоборот, что было бы больше похоже на:
from h in context.Authentications
from t in h.Authorizations.DefaultIfEmpty()
.
Если вы можете дать нам лучшее представление о модели данных и какие данные вы ожидаете выйти из этого, мы можем легче объяснить, как этот запрос будет смотреть в LINQ.Предполагая, что ваши отношения соответствуют тому, что подразумевается SQL, вы должны быть в состоянии получить то, что вы хотите использовать следующие запросы LINQ:
var query = from h in context.Authentications
from t in h.Authorizations.DefaultIfEmpty()
select new
{
h.AuthenticationId,
h.Username,
Permissions = t == null ? null : t.Permissions,
Organizations = t == null ? new EntitySet<Organization>() : t.Organizations
};
var query2 = from x in query
from o in x.organizations.DefaultIfEmpty()
select new
{
AUTHENTICATION_ID = (short?)x.AuthenticationId,
x.Username,
x.Permissions,
OrganizationIdentifier = o == null ? null : o.OrganizationIdentifier,
OrganizationID = o == null ? (short?)null : o.OrganizationID
};
. Другие советы
Учитывая иностранные ключи, которые существуют в диаграмме вопроса, как насчет чего-то вроде этого?
var query = from a in context.Authentications
select new
{
a.AuthenticationID,
a.Username,
a.Authorisations.Permissions ?? false,
a.Authorisations.Organisations.OrganisationIdentifier ?? 0
a.Authorisations.Organisations.OrganisationID ?? 0
};
. Я пошел вперед и переместил весь запрос в сохраненную процедуру в базе данных.Это решает проблему, избегая LINQ и ObjectBuilder в первую очередь.