你怎么懒载嵌套的名单但实际并未执行的查询?使用非常基本的例子,说我有:

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填充的依赖关系在正确的时间。注意到会到这个路线,有其自身的问题,但这是可以做到的。

这里有一个链接到你开始在这条路线

实现POCO s在皇宫SQL

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top