实体框架上的急切加载导航属性

Posted

技术标签:

【中文标题】实体框架上的急切加载导航属性【英文标题】:Eager load navigation properties on Entity Framework 【发布时间】:2016-05-20 18:55:26 【问题描述】:

我一直在互联网上寻找解决问题的方法,但还没有找到任何可行的方法。

我有一个像这样选择新 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 属性,这样它在循环访问客户时不会多次访问数据库。我认为包含会急切加载导航属性。

我知道我可以在 myDTO 中放置一个 order 属性并以这种方式加载它,但我很好奇是否可以采用上述方式。

谢谢!

【问题讨论】:

【参考方案1】:

我不确定您是否可以在仍然启用延迟加载的情况下预先加载属性。如果您愿意为 CustomersOrders 属性或整个上下文禁用延迟加载,那么它应该按照您呈现的方式工作。

您可以通过从 Orders 属性中删除 virtual 关键字或通过添加以下内容为整个 dbContext 关闭它来做到这一点:

     this.Configuration.LazyLoadingEnabled = false;

到您的 dbContext 构造函数。然后以您呈现的方式急切加载它应该可以正常工作。

但是,请记住,您将来总是需要预先加载该属性(或所有导航属性,具体取决于您采用的方法)。

【讨论】:

【参考方案2】:

正如您所发现的,急切加载 (Include) 不起作用 when the query result is a projection。有时这很麻烦,在像你这样的情况下,当结果包含个完整实体时,我真的不明白为什么这些实体没有启用导航属性Includeed。

无论如何,这是您必须找到解决方法的限制。正如你所说,包括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 已填充,因为当上下文包含相关实体时,EF 会自动填充导航属性(也称为关系修复)。必须禁用延迟加载,因为myDTO.Customer.Orders 没有标记为内部加载,因此解决它仍会触发延迟加载。

【讨论】:

以上是关于实体框架上的急切加载导航属性的主要内容,如果未能解决你的问题,请参考以下文章

渴望加载实体框架核心

使用急切加载时,实体框架是不是将所有相关实体加载到无限深度

代码优先实体框架。急切加载,验证然后保存导致错误

我正在尝试使用实体框架进行急切加载,其中我在区域和客户端之间具有一对多的关系

如何使用代码优先实体框架在 ASP.Net MVC3 中重新加载多对多导航属性

当延迟加载禁用时,如何通过实体框架仅将导航属性的特定属性包含到查询中?