Потенциальная область, которую я вижу, это то, что вы, возможно, загружаете из базы данных гораздо больше данных, чем требуется для сериализации в AbstractProductListItemDto
.Например, у вашего Product
могут быть поля, подобные приведенным ниже:
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Однако у вашего окончательного DTO может быть только одно или два из этих свойств, например:
public class AbstractProductListItemDto
{
public string ProductId { get; set; }
public string ProductName { get; set; }
}
Это также может быть верно для других таблиц, которые вы включаете (Options
, Lists
, Rules
и т. Д.), Особенно для таблиц, которые один-ко-многим , которыеможет легко разобрать количество запрашиваемых строк / столбцов.
Потенциальный способ оптимизировать это состоит в том, чтобы выполнить проекцию самостоятельно как часть запроса LINQ.Это позволит использовать функцию EF Core, в которой он выбирает только те столбцы из базы данных, которую вы указали.Например:
Это позволит выбрать все столбцы из таблицы продуктов
var results = _context.Products.ToList();
Это позволит выбрать только столбцы Id и Name из таблицы продуктов,что приводит к меньшему использованию памяти
var results = _context.Products.Select(x => new ProductDto {
Id = x.Id,
Name = x.Name,
}
Из этого вопроса я не знаю всех свойств всех элементов, которые вы отображаете, так что это будет зависеть от вас, если вы захотите это сделатьэто отображение вручную.Важная часть заключается в том, что вам нужно будет сделать это при вызове Select()
до вашего звонка ToList()
по вашему запросу.
Однако существует потенциальная возможностьярлык, если вы используете Automapper
Automapper включает в себя ярлык, который пытается написать эти прогнозы для вас.Это может не работать в зависимости от того, сколько дополнительной логики происходит в Automapper, но это может стоить попробовать. Вы хотите прочитать о ProjectTo<>()
методе .Если бы вы использовали проекцию, код, вероятно, выглядел бы примерно так:
Редактировать: в комментариях было правильно указано, что вызовы Include () не нужны при использовании ProjectTo<>()
.Вот более короткий образец с оригиналом, включенным под ним
Обновлено:
using AutoMapper.QueryableExtensions;
// ^^^ Added to your usings
//
[HttpGet("test")]
public ActionResult Test()
{
var projection = _context.Products.ProjectTo<AbstractProductListItemDto>(_mapper.ConfigurationProvider);
return Ok(projection.ToList());
}
Оригинал:
using AutoMapper.QueryableExtensions;
// ^^^ Added to your usings
//
[HttpGet("test")]
public ActionResult Test()
{
var results = _context.Products
.Include(x => x.Images)
.Include(x => x.Options)
.ThenInclude(x => x.Lists)
.ThenInclude(x => x.PriceChangeRule)
.Include(x => x.Options)
.ThenInclude(x => x.Lists)
.ThenInclude(x => x.Items)
.ThenInclude(x => x.PriceChangeRule)
.Include(x => x.Options)
.ThenInclude(x => x.Lists)
.ThenInclude(x => x.Items)
.ThenInclude(x => x.SupplierFinishingItem)
.ThenInclude(x => x.Parent)
.Include(x => x.Category)
.ThenInclude(x => x.PriceFormation)
.ThenInclude(x => x.Rules)
.Include(x => x.Supplier)
.ThenInclude(x => x.PriceFormation)
.ThenInclude(x => x.Rules)
.Include(x => x.PriceFormation)
.ThenInclude(x => x.Rules)
.AsNoTracking(); // Removed call to ToList() to keep it as IQueryable<>
var projection = results.ProjectTo<AbstractProductListItemDto>(_mapper.ConfigurationProvider);
return Ok(projection.ToList());
}