NHibernate - 查询后可以获取一个集合吗?

时间:2011-08-11 15:54:51

标签: nhibernate lazy-loading

在使用.Fetch

进行实际查询时,有很多关于获取和急切加载的文献

但是,一旦我有一个加载的实体 - 一个空的集合(因为我选择不在查询时因为笛卡尔积的副作用而急于加载),我可以选择稍后加载一个集合,比如说在我完成了一些分页后,我有一个具体的项目列表?

类似的东西:

var list = (some linq over Session.Query<Entity>)
.Take(10).Skip(2)
.Fetch(x => x.MyCollection)
.ToList();

Session.Fetch<Entity>(list, l => l.OtherCollection);

修改 关键是 - 我已经在查询中获取了2个子集合 - 使得查询和结果集已经相当大(参见nhibernate Cartesian产品)。我想分页结果,获取10的列表然后可选地返回数据库以填充分页(10,比方说)结果的子集合属性。这是性能考虑因素。

2 个答案:

答案 0 :(得分:1)

发出此查询

/*we dont need the result*/Session.QueryOver<Entity>()
    .Where(x => x.Id.IsIn(list.Select(l => l.Id)))
    .Fetch(l => l.OtherCollection)
    .ToList();

然后nhibernate应该初始化实体上的集合

编辑:

改善初始加载时间,请参阅http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate

那么你可以做exmaple

var results = (some linq over Session.Query<Entity>)
    .Take(10).Skip(2)
    .ToList();

var q = Session.QueryOver<Entity>()
    .Where(x => x.Id.IsIn(list.Select(l => l.Id)))
    .Fetch(l => l.MyCollection)
    .ToFuture();

Session.QueryOver<Entity>()
    .Where(x => x.Id.IsIn(list.Select(l => l.Id)))
    .Fetch(l => l.OtherCollection)
    .ToFuture();

Session.QueryOver<Entity>()
    .Where(x => x.Id.IsIn(list.Select(l => l.Id)))
    .Fetch(l => l.ThirdCollection)
    .ToFuture();

return q.ToList()

答案 1 :(得分:0)

我刚刚开始阅读有关NHibernate中的期货和预测的内容,这看起来很有希望作为解决方案...当我发现它时会发布更多内容。

这是一个解决方案:http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate,但我仍然不喜欢它,因为我的查询本身非常昂贵(使用'%like%@ + paging),所以执行3或4次只是为了加载集合看起来很贵

修改

这就是我所拥有的。查看生成的sql,正在运行正确的sql并返回预期结果,但返回结果的集合为null。你能看到缺少的东西吗?:

public List<Company> CompaniesForLoggedInUser(int pageSize, int pageNumber)
    {
      var list =
        QueryForCompaniesFor(SecurityHelper.LoggedInUsername)
          .Page(pageNumber, pageSize)
          .ToList()
          .FetchCompanyCollections(Session);
      return list;
    }

internal static class CompanyListExtensions
  {
    internal static List<Company> FetchCompanyCollections(this List<Company> companies, ISession session)
    {
      var ids = companies.Select(l => l.Id).ToArray();

      session.QueryOver<Company>()
        .Where(x => x.Id.IsIn(ids))
        .Fetch(l => l.Properties).Eager()
        .Future();

      return session.QueryOver<Company>()
        .Where(x => x.Id.IsIn(ids))
        .Fetch(l => l.UserAccessList).Eager()
        .Future()
        .ToList();
    }
  }