正如标题所示,我正在寻找一种方法来结合包含一个 where 子句。
这是我的情况:我负责支持一个充满代码异味的大型应用程序。更改太多代码会导致到处出现错误,因此我正在寻找最安全的解决方案。
假设我有一个对象 Bus 和一个对象 People(Bus 有一个导航道具 Collection of People)。在我的查询中,我需要选择只有醒着的乘客的所有巴士。这是一个简单的虚拟示例
在当前代码中:
var busses = Context.Busses.Where(b=>b.IsDriving == true);
foreach(var bus in busses)
{
var passengers = Context.People.Where(p=>p.BusId == bus.Id && p.Awake == true);
foreach(var person in passengers)
{
bus.Passengers.Add(person);
}
}
在此代码之后,上下文被释放,在调用方法中,生成的总线实体被映射到 DTO 类(实体的 100% 副本)。
此代码会导致多次调用 DB,这是不可行的,所以我在MSDN 博客上找到了这个解决方案
这在调试结果时效果很好,但是当实体映射到 DTO(使用 AutoMapper)时,我得到一个异常,即上下文/连接已关闭并且无法加载对象。(上下文总是关闭不能改变这一点:()
所以我需要确保 Selected Passengers 已经加载(导航属性上的 IsLoaded 也是 False)。如果我检查Passengers 集合,Count 也会抛出异常,但是在Passegers 集合上还有一个集合,称为“包装的相关实体”,其中包含我过滤的对象。
有没有办法将这些包装的相关实体加载到整个集合中?(我无法更改自动映射器映射配置,因为它在整个应用程序中使用)。
还有其他方法可以获取活跃的乘客吗?
欢迎任何提示...
编辑
Gert Arnold 的回答不起作用,因为没有急切地加载数据。但是当我简化它并删除它的加载位置时。这真的很奇怪,因为执行 sql 在这两种情况下都会返回所有乘客。所以将结果放回实体时肯定有问题。
Context.Configuration.LazyLoadingEnabled = false;
var buses = Context.Busses.Where(b => b.IsDriving)
.Select(b => new
{
b,
Passengers = b.Passengers
})
.ToList()
.Select(x => x.b)
.ToList();
编辑2
经过一番挣扎,Gert Arnold 工作的答案!正如 Gert Arnold 建议的那样,您需要禁用延迟加载并保持关闭。这将要求对应用程序进行一些额外的更改,因为上一个开发人员喜欢延迟加载 -_-