Я использую NHibernate 3.2 с FluentNHibernate и Linq для NHibernate.Я хочу использовать Linq для 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, кроме его идентификатора.Однако, если я не использую FetchMany / ThenFetchMany, у меня возникает проблема N + 1, и для каждого ребенка и внука выполняется поездка в базу данных, что также неприемлемо.
В качестве альтернативы я мог бы сделатьЗапредельно большие поля LazyLoad.Однако большинство приложений, использующих класс Child, должны использовать ProhibitivelyLargeField, но они не хотят загружать RarelyUsedLargeField, который уже является LazyLoad.Насколько я понимаю, загрузка одного свойства LazyLoad приводит к загрузке всех из них, поэтому это решение приведет к сбою в обычном случае использования.
Есть ли способ получить именно ту информацию, которую я ищу, используяLinq для NHibernate, или мне нужно использовать API Criteria Query?
Спасибо!
отредактировано, чтобы привести пример того, почему создание ProhibitivelyLargeField LazyLoad может быть нежелательным