我正在使用 NHibernate 3.2 与 FluentNHibernate 和 Linq to NHibernate。我想使用 Linq to NHibernate 来急切地加载集合的所有孙子,而不必加载孩子。例如,假设我有以下课程:
public class Parent
{
public virtual int Id { get; set; }
public virtual IList<Child> Children { get; set; }
}
public class ParentMap : ClassMap<Parent>
{
Id(x => x.Id);
HasManyToMany(x => x.Children).ExtraLazyLoad();
}
public class Child
{
public virtual int Id { get; set; }
public virtual IList<Parent> Parents { get; set; }
public virtual IList<Grandchild> Grandchildren { get; set; }
public virtual ProhibitivelyLargeType ProhibitivelyLargeField { get; set; }
public virtual ProhibitivelyLargeType RarelyUsedLargeField { get; set; }
}
public class ChildMap : ClassMap<Child>
{
Id(x => x.Id);
HasManyToMany(x => x.Parents).ExtraLazyLoad();
HasManyToMany(x => x.Grandchildren).ExtraLazyLoad();
Map(x => x.ProhibitivelyLargeField);
Map(x => x.RarelyUsedField).LazyLoad();
}
public class Grandchild
{
public virtual int Id { get; set; }
public virtual IList<Child> Children { get; set; }
public virtual int Age { get; set; }
}
public class GrandchildMap : ClassMap<Grandchild>
{
Id(x => x.Id);
HasManyToMany(x => x.Children).ExtraLazyLoad();
Map(x => x.Age);
}
对于每个父母,我想找出该父母所有孙辈的总年龄。我可以使用以下方法这样做:
Dictionary<Parent, int> grandchildAges = session.Query<Parent>()
.FetchMany(p => p.Children)
.ThenFetchMany(c => c.Grandchildren)
.AsEnumerable()
.ToDictionary(
p => p,
p => p.Children.SelectMany(c => c.Grandchildren).Sum(g => g.Age)
);
这种方法产生正确的结果。但是,它需要加载所有子对象。Child 包含一个 ProhibitivelyLargeType 类型的字段,它不是延迟加载的,所以我真的希望不加载任何关于 Child 的内容,只加载它的 ID。但是,如果我不使用 FetchMany/ThenFetchMany,那么我就会遇到 N + 1 问题,并且每个 Child 和 Grandchild 都需要访问数据库,这也是不可接受的。
或者,我可以制作 ProhibitivelyLargeField LazyLoad。但是,大多数使用 Child 类的应用程序都需要使用 ProhibitivelyLargeField,但又不想加载 RarelyUsedLargeField,这已经是 LazyLoad。据我了解,加载一个 LazyLoad 属性会导致所有这些属性都被加载,因此此解决方案会使正常用例陷入困境。
有没有办法使用 Linq to NHibernate 获取我正在寻找的信息,或者我是否必须使用 Criteria Query API?
谢谢!
编辑以举例说明为什么制作 ProhibitivelyLargeField LazyLoad 可能是不可取的