这是使用ThenFetch()加载多个集合的正确方法吗?

时间:2010-08-03 15:18:52

标签: nhibernate orm linq-to-nhibernate fetching-strategy

我正在尝试使用NHibernate 3 alpha 1热切地加载所有集合。我想知道这是否正确使用ThenFetch()?

具有复数名称的属性是集合。其他只是一个对象。

            IQueryable<T> milestoneInstances = Db.Find<T, IQueryable<T>>(db =>
            from mi in db
            where mi.RunDate == runDate
            select mi).Fetch(mi => mi.Milestone)
                .ThenFetch(m => m.PrimaryOwners)
                .Fetch(mi => mi.Milestone)
                .ThenFetch(m => m.SecondaryOwners)
                .Fetch(mi => mi.Milestone)
                .ThenFetch(m => m.Predecessors)
                .Fetch(mi => mi.Milestone)
                .ThenFetch(m => m.Function)
                .Fetch(mi => mi.Milestone)
                .ThenFetchMany(m => m.Jobs)
                .ThenFetch(j => j.Source)
                ;

我想在NHibernate forums中提出这个问题,但不幸的是,禁止访问谷歌群组。我知道Fabio就在这里,所以也许来自NHibernate团队的人可以对此有所了解? 感谢

4 个答案:

答案 0 :(得分:10)

显然,在这种情况下,没有“正确”的方式来使用ThenFetch。您的示例工作正常,但生成的SQL包含许多Milestone的连接,这不是正确的。

使用IQueryOver代替IQueryable,您可以在Fetch中使用complex syntax

Fetch(p => p.B) 
Fetch(p => p.B.C) // if B is not a collection ... or 
Fetch(p => p.B[0].C) // if B is a collection ... or 
Fetch(p => p.B.First().C) // if B is an IEnumerable (using .First() extension method) 

所以在你的情况下,它将是:

query // = session.QueryOver<X>()
    .Fetch(mi => mi.Milestone).Eager
    .Fetch(mi => mi.Milestone.PrimaryOwners).Eager
    .Fetch(mi => mi.Milestone.SecondaryOwners).Eager
    .Fetch(mi => mi.Milestone.Predecessors).Eager
    .Fetch(mi => mi.Milestone.Function).Eager
    .Fetch(mi => mi.Milestone.Jobs).Eager
    .Fetch(mi => mi.Milestone.Jobs.First().Source).Eager

答案 1 :(得分:3)

你缺少的一件事是你应该使用FetchMany()而ThenFetchMany()是子属性是一个集合。

答案 2 :(得分:1)

        IQueryable<T> milestoneInstances = Db.Find<T, IQueryable<T>>(db =>
        from mi in db
        where mi.RunDate == runDate
        select mi);

var fetch = milestoneInstances.Fetch(f => f.Milestone);
fetch.ThenFetch(f => f.PrimaryOwners);
fetch.ThenFetch(f => f.SecondaryOwners);
//...

答案 3 :(得分:0)

正如leora所说,确保在获取您使用的儿童收藏品时

FetchMany()

ThenFetchMany()

新的Fetch应该从root中获取,但这并不总是会发生。有时您需要将它们创建为单独的查询,或使用Criteria Futures批量处理多次获取。