私はNHibernate3.2とFluentNHibernateおよびLinqtoNHibernateを使用しています。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の問題が発生し、子と孫ごとにデータベースにアクセスする必要があります。これも受け入れられません。
または、ProhibitivelyLargeFieldLazyLoadを作成することもできます。ただし、Childクラスを使用するほとんどのアプリケーションは、ProhibitivelyLargeFieldを使用する必要がありますが、すでにLazyLoadであるRarelyUsedLargeFieldをロードする必要はありません。私が理解しているように、1つのLazyLoadプロパティをロードすると、すべてのプロパティがロードされるため、このソリューションは通常のユースケースを台無しにします。
Linq to NHibernateを使用して探している情報だけを取得する方法はありますか、それともCriteria Query APIを使用する必要がありますか?
ありがとう!
ProhibitivelyLargeFieldLazyLoadを作成することが望ましくない理由の例を示すために編集