Linq2Sql-你怎么懒载列的嵌套?
-
16-09-2019 - |
题
你怎么懒载嵌套的名单但实际并未执行的查询?使用非常基本的例子,说我有:
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,然后我们基本上有一个泄漏从我们达到我们的领域模型,这可能是非常非常不好的未来。
所以我如何去这样做正确?
- 它是一个问题的确定 正确的背景下?如果是这样,我们将会做 此在储存库层,或 服务层?
- 做我的一半融合在一起的服务层和我的储存库层得到 非常具体的服务的方法吗?
- 还是我失去了一些东西完全?(仍然相对较新的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领域。这是映射到我们域对象的东西也许我们应该做了,在业务层?
解决方案
你做的,它通过回IQueryables而不是ILists.
ToList()使查询,以立即执行,因为一个转换,必须执行从IQueryable到IList.
只要你返回IQueryables懒加载应该推迟执行,直到的数据实际需要,即当ToList()。
我不能找到一个参考的时刻,但我的理解是,如果你做过这种方式,皇宫sql有机会优化SQL它送到服务器。换句话说,它最终将读这些记录:
GetCityBlocks().ForOwner("Guido")
而不是这些记录:
GetCityBlocks()
其他提示
你可以尝试一种不同的方法绘制你域的对象,使它的工作。问题是,不管你做什么(除非你改变你的名单,以IQueryables域中的对象)你最终会ToList()ing而你映射。
其他的方式让linq2Sql做的映射到你的POCOs通过创建一个定义属性和未使用的的设计师为映射:),这样你跟你的领域模型清洁和让linq2Sql填充的依赖关系在正确的时间。注意到会到这个路线,有其自身的问题,但这是可以做到的。
这里有一个链接到你开始在这条路线