【发布时间】:2019-04-19 01:17:15
【问题描述】:
我正在制作一个 Asp.net Core Api 和一个控制器的操作,我需要返回一个 DTO 的 IQueryable,但其中一个属性是另一个 DTO 的 IEnumerable,在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; }
}
还有 DTO
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 的原因。
我正在使用 Select 将每个元素投影到 DTO,那里没有问题,因为我可以在 ASP.NET Core Web 服务器输出上看到系统只向数据库发出一个请求(以获取客户),但是当我尝试将 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
})
});
}
如果我在使用 Select 投影元素之前调用 ToList(),它将只向数据库发出一个请求(如预期的那样),但我需要返回一个 IQueryable,因为我使用的是 OData,以便前端应用程序可以直接对数据库执行查询,即使只是一个 DTO
我已经试过这样放
Orders = s.Orders.Any() ? s.Orders.Select(so => new OrderDTO
{
OrderNumber = so.OrderNumber
}) : new List<OrderDTO>()
它部分解决了问题,因为如果 100 个客户中只有 50 个有订单,则 EF 只会向数据库发出 50 个请求。
我想知道这个问题是否有解决方案,因为我不希望应用程序在每次用户调用 API 的这个端点时对数据库进行数百次查询。
【问题讨论】:
标签: c# linq asp.net-core entity-framework-core odata