Как извлечь логику проекции в отдельные методы для запросов EF Core LINQ?C#

Место общения программистов C#
Ответить
Anonymous
 Как извлечь логику проекции в отдельные методы для запросов EF Core LINQ?

Сообщение Anonymous »

Как я могу извлечь логику проекции для запросов EF Core LINQ в отдельные методы, чтобы сделать код более чистым или повторно использовать код для разных проекций?
В качестве примера у меня есть эта проекция. Он возвращает данные о местоположении с вложенными изображениями обложек. URI изображения, ширина и высота извлекаются из коллекции изображений.

Код: Выделить всё

List Locations;

var query = dbContext.Location.AsNoTracking()
.Select(location => new LocationMLResponse(
location.Id.Value,
location.Name.ToStringDictionary(),
location.CoverImages
.Join(dbContext.Image.AsNoTracking(),
danceCoverImage => danceCoverImage.ImageId,
image => image.Id,
(danceCoverImage, image) => new ImageItemResponse(
danceCoverImage.ImageId.Value,
danceCoverImage.DisplayOrder,
danceCoverImage.Language == null ? null : danceCoverImage.Language.Tag,
danceCoverImage.ScreenSize == null ? null : danceCoverImage.ScreenSize.Value,
danceCoverImage.FocusPointX,
danceCoverImage.FocusPointY,
image.Uri.ToString(),
image.MetaData.Width,
image.MetaData.Height
)).ToList(),
location.Address.MapToDto(),
location.Created,
location.LastModified,
location.Version
));

Locations = await query.ToListAsync();
Я постарался сделать код более читабельным и извлечь методы для сопоставления:

Код: Выделить всё

var query = dbContext.Location.AsNoTracking()
.Select(location => MapToLocationResponse.MLResponse(dbContext, location));

internal static class MapToLocationResponse
{
public static LocationMLResponse MLResponse(VCDbContext dbContext, Location location)
{
return new LocationMLResponse(
location.Id.Value,
location.Name.ToStringDictionary(),
location.CoverImages
.Join(dbContext.Image.AsNoTracking(),
danceCoverImage => danceCoverImage.ImageId,
image => image.Id,
(danceCoverImage, image) => Mappings.MapToImageItemResponse(danceCoverImage, image)).ToList(),
location.Address.MapToDto(),
location.Created,
location.LastModified,
location.Version
);
}
}

internal static partial class Mappings
{
public static ImageItemResponse MapToImageItemResponse(ImageItem imageItem, Image image)
{
return new ImageItemResponse(
imageItem.ImageId.Value,
imageItem.DisplayOrder,
imageItem.Language == null ? null : imageItem.Language.ToString(),
imageItem.ScreenSize == null ? null : imageItem.ScreenSize.ToString(),
imageItem.FocusPointX,
imageItem.FocusPointY,
image.Uri.ToString(),
image.MetaData.Width,
image.MetaData.Height
);
}
}
Этот код создает следующий запрос:

Код: Выделить всё

SELECT [l].[LocationId], [l].[Created], [l].[CreatedBy], [l].[CreatedInNameOf], [l].[LastModified], [l].[LastModifiedBy], [l].[LastModifiedInNameOf], [l].[Name], [l].[TId], [l].[Version], [l].[Address_City], [l].[Address_CountryId], [l].[Address_CountryName], [l].[Address_DeliveryInstruction], [l].[Address_State], [l].[Address_Street], [l].[Address_StreetAffix], [l].[Address_StreetNumber], [l].[Address_ZipCode], [l0].[TId], [l0].[DisplayOrder], [l0].[FocusPointX], [l0].[FocusPointY], [l0].[ImageId], [l0].[Language], [l0].[LocationId], [l0].[ScreenSize]
FROM [VC].[Location] AS [l]
LEFT JOIN [VC].[LocationCoverImage] AS [l0] ON [l].[LocationId] = [l0].[LocationId]
ORDER BY [l].[LocationId]
Отсутствует соединение с таблицей изображений и выбор полей изображения.
Я пробовал сопоставление только с одним вложением:

Код: Выделить всё

 List Locations;

var query = dbContext.Location.AsNoTracking()//.AsSplitQuery()
.Select(location => new LocationMLResponse(
location.Id.Value,
location.Name.ToStringDictionary(),
location.CoverImages
.Join(dbContext.Image.AsNoTracking(),
danceCoverImage => danceCoverImage.ImageId,
image => image.Id,
(danceCoverImage, image) =>  Mappings.MapToImageItemResponse(danceCoverImage, image)).ToList(),
location.Address.MapToDto(),
location.Created,
location.LastModified,
location.Version
));

Locations = await query.ToListAsync();
Это работает. Проекция создает тот же запрос, что и полная проекция сверху.
(Примечание: с созданным запросом связана общая проблема, которую я опубликовал в разделе вопросов EF Core GitHub.
Существует ли ограничение на вложение? Проблема в объединении? Есть ли другие варианты разделения логики, чтобы EF Core создавал полный запрос?

Версия EF Core: 8.0.8

Поставщик базы данных: Microsoft.EntityFrameworkCore.SqlServer

Целевая платформа: NET 8.0

Операционная система: Win 11

Visual Studio 2022 17.11.4

Подробнее здесь: https://stackoverflow.com/questions/790 ... inq-querie
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»