LEFT OUTER JOIN
перевод кажется наилучшим для такого сценария.
Теоретически, переводчик запросов EF Core должен иметь возможность объединять общие выражения FirstOrDefault()
в один LEFT OUTER JOIN
, как это делается для необязательной ссылки.Навигационные свойства.
На практике (по состоянию на последнее время в EF Core 2.2) это не выполняется, и для каждого выбранного поля создается отдельный коррелированный подзапрос.
Предполагая, что каждый тип продукта имеет 0 или 1 локализацию для конкретного языка, желаемый перевод может быть достигнут с помощью SelectMany
, например:
var models = await products.SelectMany(
product => product.ProductType.ProductTypeLocalizations
.DefaultIfEmpty()
.Where(ptl => ptl == null || ptl.Language == "en"),
(product, ptl) => new
{
Id = product.ProductId,
Price = product.Price,
ProductType = new
{
Id = product.ProductType.ProductTypeId,
Name = ptl.Name,
Description = ptl.Description
}
})
.ToListAsync();
или эквивалентной и более удобочитаемой версии.используя синтаксис запроса LINQ:
var models = await (
from product in products
let pt = product.ProductType
from ptl in pt.ProductTypeLocalizations.DefaultIfEmpty()
where ptl == null || ptl.Language == "en"
select new
{
Id = product.ProductId,
Price = product.Price,
ProductType = new
{
Id = pt.ProductTypeId,
Name = ptl.Name,
Description = ptl.Description
}
}).ToListAsync();