【发布时间】:2012-02-13 17:07:38
【问题描述】:
我正在使用 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 可能是不可取的
【问题讨论】:
-
是否将
ProhibitivelyLargeType定义为延迟加载选项? -
@Firo 不,ProhibitivelyLargeField 不能被延迟加载。
-
因为...?我还没有看到一个禁用延迟加载的有效示例。
-
@Diego 我的理解是加载任何 LazyLoad 属性会导致加载所有 LazyLoad 属性,这对于 Child 类的普通消费者来说可能是不希望的。问题已更新以澄清。
标签: c# nhibernate linq-to-nhibernate eager-loading grandchild