我一直在网上搜索我的问题的解决方案,但找不到任何有效的方法。
我有一个选择新DTO的查询:
List<myDTO> query = (from c in db.Customers
.Include(x => x.Orders)
where customerId = 5
select new myDTO
{
Customer = c,
...
}).ToListAsync();
foreach (var custDto in query)
{
//this is lazy loaded
var customerOrder = custDto.Customers.Orders;
}
我的问题是当我尝试导航到query.Customers.Orders时,它是延迟加载的。我想急切加载Orders属性,以便在循环访问客户时不会多次访问数据库。我认为让include会急切加载导航属性。
我知道我可以在myDTO中放置一个订单属性并以这种方式加载它,但我很好奇是否可能采用上述方式。
谢谢!
答案 0 :(得分:0)
我不确定您是否可以在仍启用延迟加载的情况下急切加载属性。如果您愿意仅针对Orders
的{{1}}属性或整个上下文禁用延迟加载,那么它应该按您呈现的方式工作。
您可以通过从Customers
属性中删除virtual
关键字,或者通过添加以下内容为整个dbContext关闭它来执行此操作:
Orders
到你的dbContext构造函数。然后急切加载您呈现它的方式应该可以正常工作。
但是,请记住,您将来必须始终加载该属性(或所有导航属性,具体取决于您采用的方法)。
答案 1 :(得分:0)
正如您所知,急切加载(Include
)不起作用when the query result is a projection。这有点令人讨厌,在像你这样的情况下,当结果包含完整实体时,我真的不明白为什么这些实体没有启用导航属性Include
ed。
无论如何,这是一个限制,你必须找到一个解决办法。如你所说,包括像Orders = c.Orders
这样的属性是可能的。你可以做的另一件事是
db.Configuration.LazyLoadingEnabled = false;
var intermed = (from c in db.Customers
where customerId = 5
select new
{
Customer = c,
...
Orders = c.Orders
}).ToListAsync();
var dtos = intermed.Select(x => new myDTO
{
Customer = x.Customer,
...
}).ToList();
您会注意到myDTO.Customer.Orders
已填充,因为当上下文包含相关实体(也称为 relationship fixup )时,EF会自动填充导航属性。必须禁用延迟加载,因为myDTO.Customer.Orders
未在内部加载标记,因此解决它仍会触发延迟加载。