EF Core 5.0 Union Linq Query с вложенными выборками не работает
Цель:
Я хочу объединить информацию из двух таблиц (entityA и entityB) с разными свойствами в один unionDto. Я пытаюсь реализовать это с помощью операции объединения для одновременной фильтрации различных сущностей в базе данных.
Но для структуры, которую я использую, требуются версии, которые необходимо отфильтровать перед запросом на объединение.
Некоторая дополнительная информация:
В последнем запросе я пытаюсь сделать следующее: сначала я проецирую информацию из таблицы entityA и entityB в универсальный "анонимный" тип (с объединением). Затем я пытаюсь применить разбиение на страницы, а затем я пытаюсь "спроецировать" новый анонимный результат на UnionDto. Таким образом, это приведет к одному UnionDto, который будет иметь "информацию из двух разных таблиц".
Я создал пример своей проблемы с двумя объектами, у которых есть версии:
Сущности:
class entityA {
public List<VersionA> Versions;
public Guid CreatedBy;
}
class entityB {
public List<VersionB> Versions;
public Guid CreatedBy;
}
class VersionA {
public string TitleA;
public Instant EffectiveTo;
}
class VersionB {
public string TitleB;
public Instant EffectiveTo;
}
class UnionDto{
public string Title;
public Guid Creator;
}
Я задаю такой запрос:
var queryA = databaseContext.Set<entityA>()
.Select(entity => new
{
Versions = entity.Versions
.Where(version => version.EffectiveTo > now) /* Filtering newest entity Version */
.Select(versionDetail => new /* Selecting only the Title of this Version */
{
Title = versionDetail.TitleA
})
.ToList(),
Creator = entity.CreatedBy,
});
var queryB = databaseContext.Set<entityB>()
.Select(entity => new
{
Versions = entity.Versions
.Where(version => version.EffectiveTo > now)
.Select(versionDetail => new
{
Title = versionDetail.TitleB
})
.ToList(),
Creator = entity.CreatedBy,
});
Выполнение запроса:
var unionDto = await queryA
.Union(queryB)
.Skip(0)
.Take(20)
.Select(x => new UnionDto
{
Title= x.Versions.FirstOrDefault() == null ? null :
x.Versions.FirstOrDefault().Title,
Creator= x.Creator,
})
.ToListAsync();
Похоже, что я не могу использовать подвыборки внутри запроса на объединение, и я получаю следующую ошибку:
Установить операции: поддержка при размещении после оценки клиента в проекции #16243
Я не знаю, что мне нужно сделать, чтобы обойти эту проблему, так как я действительно не хочу обрабатывать все свои объекты отдельно с отдельными запросами к базе данных.
В настоящее время используется ядро Ef Версия: 5.0.100-превью
Это просто пример. Это потребовалось бы как минимум для 10 объектов, что привело бы к высокому трафику базы данных, если бы это было сделано для каждого объекта отдельно.
Есть идеи?
2 ответа
Если вам нужен только заголовок первой версии из каждого набора записей, ваш запрос можно упростить, и EF Core сможет перевести этот запрос.
var queryA =
from entity in databaseContext.Set<entityA>()
from version in entity.Versions
where version.EffectiveTo > now
select new
{
Title = version.Title,
Creator = entity.CreatedBy
}
var queryB =
from entity in databaseContext.Set<entityB>()
from version in entity.Versions
where version.EffectiveTo > now
select new
{
Title = version.Title,
Creator = entity.CreatedBy
}
var versions = queryA.Union(queryB);
var unionDto = await versions
.Skip(0)
.Take(20)
.Select(x => new UnionDto
{
Title = x.Title,
Creator = x.Creator,
})
.ToListAsync();
EF Union set Отслеживается с помощью операций Set над проекциями, не являющимися сущностями, с разными аспектами. Проблема
Теперь исправлено с помощью EF8 Preview 3, как показано здесь.