最新消息 :此功能现已添加到Entity
framework核心中。
您可以通过查询以下对象
Context.Configuration.LazyLoadingEnabled = false;// Or: Context.Configuration.ProxyCreationEnabled = false;var buses = Context.Busses.Where(b => b.IsDriving) .Select(b => new { b, Passengers = b.Passengers .Where(p => p.Awake) }) .AsEnumerable() .Select(x => x.b) .ToList();此处发生的情况是,您首先获取了驾驶巴士并从数据库中唤醒了乘客。然后,
AsEnumerable()从LINQ切换到Entities,再从LINQ切换到对象,这意味着将实现公共汽车和乘客,然后在内存中对其进行处理。这一点很重要,因为如果没有它,EF只会实现最终的投影
Select(x=> x.b),而不是乘客。
现在,EF具有此功能 关系修补程序 ,可以解决在上下文中实现的对象之间设置所有关联的问题。这意味着
Bus现在每个乘客都只被唤醒。
领取
ToList公交车时,您便有了想要的乘客的公交车,可以使用AutoMapper对其进行映射。
这仅在禁用延迟加载时有效。否则,在转换为DTO的过程中访问EF时,EF将为每辆巴士延迟加载 所有 乘客。
有两种方法可以禁用延迟加载。
LazyLoadingEnabled再次启用时,禁用将重新激活延迟加载。禁用
ProxyCreationEnabled将创建无法
自行
延迟加载的实体,因此
ProxyCreationEnabled再次启用后它们将不会开始延迟加载。当上下文的寿命比单个查询更长时,这可能是最佳选择。
但是…多对多
如前所述,此变通办法依赖于关系修复。然而,正如解释在这里通过Slauma,关系修正不能与许多-
to-many关联工作。如果
Bus-
Passenger是多对多,则您唯一可以做的就是自己修复它:
Context.Configuration.LazyLoadingEnabled = false;// Or: Context.Configuration.ProxyCreationEnabled = false;var bTemp = Context.Busses.Where(b => b.IsDriving) .Select(b => new { b, Passengers = b.Passengers .Where(p => p.Awake) }) .ToList();foreach(x in bTemp){ x.b.Pasengers = x.Passengers;}var busses = bTemp.Select(x => x.b).ToList();……整个事情变得越来越没有吸引力了。
第三方工具
有一个库Entityframework.DynamicFilters使它变得容易得多。它允许您为实体定义全局过滤器,随后将在查询实体时将其应用。在您的情况下,可能看起来像:
modelBuilder.Filter("Awake", (Person p) => p.Awake, true);现在,如果您愿意…
Context.Busses.Where(b => b.IsDriving) .Include(b => b.People)
…您将看到过滤器已应用于包含的集合。
您还可以启用/禁用过滤器,因此可以控制何时应用它们。我认为这是一个非常整洁的图书馆。
AutoMapper的制造商提供了一个类似的库:Entityframework.Filters
实体框架核心
从2.0.0版开始,EF-core具有全局查询过滤器。尽管这是对其功能的重要补充,但到目前为止的限制是,过滤器不能包含对导航属性的引用,而不能包含对查询的根实体的引用。希望在更高版本中,这些过滤器将获得更广泛的使用。
过滤的内容是一项长期存在的功能要求。EF核心问题可在此处找到。



