Я делаю Asp.net Core Api и одно из действий контроллера, мне нужно вернуть IQueryable DTO, но одно из свойств является IEnumerable другого DTO в отношениях один ко многим в модель базы данных EF.
Например:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Birthday { get; set; }
public List<Order> Orders { get; set; }
}
public class Order
{
public int OrderNumber { get; set; }
public Customer Customer { get; set; }
}
И ДТО
public class CustomerDTO
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<OrderDTO> Orders { get; set; }
}
public class OrderDTO
{
public int OrderNumber { get; set; }
}
Это всего лишь простой пример, потому что в моем приложении много полей в каждой таблице, и я не могу открыть все для внешнего интерфейса, поэтому я использую DTO.
Я использую Выбрать для проецирования каждого элемента в DTO, там нет никаких проблем, потому что я вижу на выходе ASP.NET Core Web Server, что система только делает один запрос к базе данных (чтобы получить Клиенты), но проблема возникает, когда я пытаюсь спроектировать OrdersDTO внутри CustomerDTO. Например, если у меня 100 клиентов, EF сделает 101 запрос к базе данных. (1 для получения клиентов и 100 для получения заказов для каждого клиента)
[HttpGet]
[EnableQuery]
public IEnumerable<CustomerDTO> Get()
{
return context.Customer
.Select(s => new CustomerDTO
{
Id = s.Id,
Name = s.Name,
Orders = s.Orders.Select(so => new OrderDTO
{
OrderNumber = so.OrderNumber
})
});
}
Если я вызову ToList () перед тем, как спроецировать элементы с помощью Select, он сделает только один запрос к базе данных (как и предполагалось), но мне нужно вернуть IQueryable, потому что я использую OData, чтобы приложение внешнего интерфейса могло выполнять запросы непосредственно к базе данных, даже если это просто DTO
Я уже пробовал ставить вот так
Orders = s.Orders.Any() ? s.Orders.Select(so => new OrderDTO
{
OrderNumber = so.OrderNumber
}) : new List<OrderDTO>()
Это решило проблему частично, потому что, если из 100 клиентов только 50 имеют заказы, EF сделает только 50 запросов к базе данных.
Я хотел бы знать, есть ли решение этой проблемы, потому что я не хочу, чтобы приложение выполняло сотни запросов к базе данных каждый раз, когда какой-либо пользователь вызывает эту конечную точку API.