Linq2Sql - 你如何懒惰加载嵌套列表?

时间:2009-08-13 23:39:00

标签: .net linq-to-sql repository-pattern lazy-loading service-layer

如何在不实际执行查询的情况下延迟加载嵌套列表?使用一个非常基本的例子,说我有:

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泄漏到我们的域模型中,这可能会在将来非常糟糕。

那么我该如何正确地做到这一点?

  • 这是一个确定问题的问题 正确的背景?如果是这样,我们会这样做 这在存储库层中,或者 服务层?
  • 我是否将Service层和我的Repository层融合在一起得到 非常具体的服务方法?
  • 或者我完全错过了什么? (对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字段的人都可以获得权力。这是映射到我们的域对象我们应该在服务层中做什么吗?

2 个答案:

答案 0 :(得分:1)

你可以通过返回IQueryables而不是IList来实现。

ToList()会导致查询立即执行,因为必须从IQueryable到IList执行转换。

只要你返回IQueryables,延迟加载应该推迟执行,直到实际需要数据,即调用ToList()时。

我目前找不到引用,但我的理解是,如果你这样做,linq to sql有机会优化它发送给服务器的SQL。换句话说,它最终会读取这些记录:

GetCityBlocks().ForOwner("Guido")

而不是这些记录:

GetCityBlocks()

答案 1 :(得分:0)

您可以尝试使用不同的方法映射域对象以使其正常工作。问题在于,无论您做什么(除非您将列表更改为域对象中的IQueryables),您将在映射时结束ToList()。

让linq2Sql通过创建自定义datacontext并且不使用设计器进行映射来让映射到POCO的另一种方式,这样就可以保持域模型的清洁,并让linq2Sql在正确的时间填充依赖项。请注意,进入此路线有其自身的问题,但可以这样做。

这是一个让你开始这条路线的链接

Achieving POCO s in Linq to SQL