Я строю логику поиска (для приложения MVC), и, если честно, я застрял!Linq to Entities с несколькими связанными объектами и UNIONs
Я потратил несколько дней на создание запроса Linq to Entities для использования проекции. Все было хорошо на поверхности, пока я не посмотрел на сгенерированный оператор SQL под ним. Удушье!
В следующий раз я потратил еще несколько дней, пытаясь избавиться от этих операторов UNION от операторов SQL, пытаясь JOINs, FROMs, INCLUDEs, что угодно, просто даст мне внутренние/левые внешние соединения с связанными объектами, загруженными.
Но я не смог сделать это успешно и все еще застрял на этом этапе.
Некоторые моменты, рассмотреть следующие вопросы:
- L2E запрос содержит несколько связанных (дочерние) объекты с проекцией (не вопрос здесь, если это не плохой дизайн, т.е. вызывая Союзов)
- Созданные сводные классы, которые соответствуют анонимные типы, например StudentSummary
- Сводные классы содержат только несколько столбцов столбцов объекта сущности по соображениям производительности - не нужно возвращать все столбцы при первоначальном поиске
- Недавно началось использование PredicateBuilder для возврата студентов из поиска, например. студенты-мужчины со специализацией ... Все хорошо в этой области (до сих пор).
Вот что я сделал до сих пор (код изменен, чтобы скрыть собственную собственность - может иметь опечаток):
query = from s in context.Students
select new StudentSummary
{
StudentID = s.StudentID,
Title = s.Title,
FullName = s.FullName,
Qualifications = s.Qualifications,
Gender = s.Gender,
CampusSummaries = (
from c in s.Campuses
select new CampusSummary
{
Name = c.Name,
LocationSummary = new LocationSummary
{
State = c.Location.State
}
}),
SpecializationSummaries = (
from sp in s.StudentSpecializations
select new StudentSpecializationSummary
{
StudentSpecializationID = sp.StudentSpecializationID,
SpecializationSummary = new SpecializationSummary
{
Name = s.Specialization.Name
}
}),
SubSpecializationSummaries = (
from ssp in s.StudentSubSpecializations
select new StudentSubSpecializationSummary
{
StudentSubSpecializationID = ssp.StudentSubSpecializationID,
SubSpecializationSummary = new SubSpecializationSummary
{
Name = s.SubSpecialization.Name
}
})
};
Мои проекционные заявления, как представляется, чтобы сделать Entity Framework генерировать следующие операторы SQL UNION, ниже приведен фрагмент код только (код изменен, чтобы скрыть собственную собственность - может иметь опечатки):
{SELECT
[UnionAll1].[StudentID] AS [C1],
[UnionAll1].[StudentID1] AS [C2],
[UnionAll1].[Title] AS [C3],
[UnionAll1].[FullName] AS [C4],
[UnionAll1].[Qualifications] AS [C5],
[UnionAll1].[Gender] AS [C6],
[UnionAll1].[C1] AS [C9],
[UnionAll1].[StudentSpecializationID] AS [C10],
[UnionAll1].[StudentSpecializationID1] AS [C11],
[UnionAll1].[StudentSpecializationID2] AS [C12],
[UnionAll1].[Name] AS [C13],
[UnionAll1].[C2] AS [C14],
[UnionAll1].[C3] AS [C15],
[UnionAll1].[C4] AS [C16],
[UnionAll1].[C5] AS [C17]
FROM (SELECT
CASE WHEN ([Join1].[StudentSpecializationID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1],
[Extent1].[StudentID] AS [StudentID],
[Extent1].[StudentID] AS [StudentID1],
[Extent1].[Title] AS [Title],
[Extent1].[FullName] AS [FullName],
[Extent1].[Qualifications] AS [Qualifications],
[Extent1].[Gender] AS [Gender],
[Join1].[StudentSpecializationID] AS [StudentSpecializationID],
[Join1].[StudentSpecializationID] AS [StudentSpecializationID1],
[Join1].[StudentSpecializationID] AS [StudentSpecializationID2],
[Join1].[Name] AS [Name],
CAST(NULL AS int) AS [C2],
CAST(NULL AS int) AS [C3],
CAST(NULL AS int) AS [C4],
CAST(NULL AS varchar(1)) AS [C5]
FROM [dbo].[Student] AS [Extent1]
LEFT OUTER JOIN (SELECT [Extent2].[StudentSpecializationID] AS [StudentSpecializationID], [Extent2].[StudentID] AS [StudentID], [Extent3].[Name] AS [Name]
FROM [dbo].[StudentSpecialization] AS [Extent2]
INNER JOIN [dbo].[Specialization] AS [Extent3] ON [Extent2].[SpecializationID] = [Extent3].[SpecializationID]) AS [Join1] ON [Extent1].[StudentID] = [Join1].[StudentID]
UNION ALL
SELECT
2 AS [C1],
[Extent4].[StudentID] AS [StudentID],
[Extent4].[StudentID] AS [StudentID1],
[Extent4].[Title] AS [Title],
[Extent4].[FullName] AS [FullName],
[Extent4].[Qualifications] AS [Qualifications],
[Extent4].[Gender] AS [Gender],
CAST(NULL AS int) AS [C2],
CAST(NULL AS int) AS [C3],
CAST(NULL AS int) AS [C4],
CAST(NULL AS varchar(1)) AS [C5],
[Join3].[StudentSubSpecializationID] AS [StudentSubSpecializationID],
[Join3].[StudentSubSpecializationID] AS [StudentSubSpecializationID1],
[Join3].[StudentSubSpecializationID] AS [StudentSubSpecializationID2],
[Join3].[Name] AS [Name]
FROM [dbo].[Student] AS [Extent4]
INNER JOIN (SELECT [Extent5].[StudentSubSpecializationID] AS [StudentSubSpecializationID], [Extent5].[StudentID] AS [StudentID], [Extent6].[Name] AS [Name]
FROM [dbo].[StudentSubSpecialization] AS [Extent5]
INNER JOIN [dbo].[SubSpecialization] AS [Extent6] ON [Extent5].[SubSpecializationID] = [Extent6].[SubSpecializationID]) AS [Join3] ON [Extent4].[StudentID] = [Join3].[StudentID]) AS [UnionAll1]
ORDER BY [UnionAll1].[StudentID1] ASC, [UnionAll1].[C1] ASC}
Я не уверен, почему союзы используются здесь. Возможно, я плохо использую проекцию. Хотя я заметил, что два или более прогноза включены в ваш оператор L2E, тогда UNIONS появляется в SQL.
Я попытался пойти в другом направлении, удалив выступы, но безуспешно пытался использовать Joins, Froms ... просто не может быть возвращено связанное дочерние объекты.
Я не могу использовать Include, поскольку я использую свои объекты подсчета по соображениям производительности.
Я также спрашиваю, правильно ли я сейчас это сделаю, то есть я иду в правильном направлении, чтобы возвращать вложенные связанные (дочерние) сущности?!?! Возможно, мне следует возвращать плоские результаты, например. Студенты, кампусы, специализации ... объекты находятся на одном уровне, т. Е. Удаляют иерархию.
Вопрос:
Если я построил это с T-SQL Я бы использовать INNER & LEFT OUTER JOIN и вернуть соответствующий ребенок вложенности объектов, а также фильтровать студентов. Это то, чего я пытаюсь достичь с Linq to Entities. Как я могу это сделать? Например. с объединениями, проекцией или любым другим ... (без UNIONs и Cast (NULL) s ...
Оцените любую помощь, даже если она просто указывает мне в правильном направлении, так как я действительно застрял здесь. Благодарю.
Запрос не работает плохо с небольшим количеством записей, но мне нужно будет выполнить профилирование SQL, чтобы точно узнать. Но хорошая точка re union all vs multiple join - не думала об этом. Прочитайте это, чтобы подтвердить. Спасибо, это помогает. –