如何在不实际执行查询的情况下延迟加载嵌套列表?使用一个非常基本的示例,假设我有:
class CityBlock {
IList<Building> BuildingsOnBlock;
Person BlockOwner;
}
class Building {
IList<Floor> FloorsInBuilding;
}
class Floor {
IList<Cubicle> EmployeeCubicles;
}
Class Cubicle {
System.Guid CubicleID;
Person CubicleOccupant;
}
然后在我的存储库层中,我有以下方法:
GetCityBlocks()
然后在服务层中,我将使用 GetCityBlocksByOwner,在这里我使用扩展方法来获取特定人拥有的城市街区,比如我们只想要 Guido 的街区:
GetCityBlocks().ForOwner("Guido")
如果我们在存储库中执行 .ToList() ,它将执行查询 - 这将是荒谬的,因为我们不知道我们在那个级别获得了谁的块。所以问题是,我们如何有效地做到这一点?
假设有 50000 个街区所有者,以及大约 1000000 个城市街区,加载所有这些街区不是一种选择。由于嵌套,使用 IQueryables 将不起作用(至少我知道没有极端的黑客攻击)。另外,如果我尝试使用 Rob Conery 的 LazyList 之类的东西,那么我们的 DAL 基本上会泄漏到我们的域模型中,这在未来可能会非常非常糟糕。
那么我该如何正确地做到这一点呢?
- 这是确定正确上下文的问题吗?如果是这样,我们会在存储层或服务层中这样做吗?
- 我是否将服务层和存储库层半融合在一起以获得非常具体的服务方法?
- 还是我完全错过了什么?(对于 Linq2Sql 来说还是比较新的东西,反正它正在被逐步淘汰,所以......)
编辑: 在存储库模式中,我们当前正在映射到我们的域对象,所以它看起来像这样:
public IQueryable<CityBlock> GetCityBlocks(){
var results = from o in db.city_blocks
let buildings = GetBuildingsOnBlock(o.block_id)
select new CityBlock {
BuildingsOnBlock = buildings,
BlockOwner = o.block_owner
};
return results;
}
为此,我们必须让建筑物获得 .ToList(),除非我们将 CityBlock 对象中的实际字段设置为 IQueryable - 这似乎不对,因为看起来好像有太多的权力授予访问 CityBlock.BuildingsOnBlock 字段的任何人。这个映射到我们的领域对象是我们应该在服务层做的吗?