NHibernate ThenFetchMany извлекает дубликаты детей - PullRequest
5 голосов
/ 01 июня 2011

У меня есть родительский объект с дочерней коллекцией, содержащей один элемент, дочерняя коллекция содержит коллекцию "внуков", содержащую 3 элемента.

Я загружаю родительский объект из базы данных, используя NHibernate, следующим образом

Parent parentObject = session.Query<Parent>()
    .FetchMany(x => x.Children)
    .ThenFetchMany(x => x.GrandChildren)
    .Where(x => x.Id = "someparentid")
    .Single();

Я обнаружил, что есть дублированные дочерние объекты (всего 3), прикрепленные к родительскому объекту, когда должен быть только один.(Есть 3 объекта внука, правильно прикрепленных к каждому дочернему элементу.) Стремление загружать дочернюю коллекцию работает только корректно.

Знаете ли вы, как я могу добиться загрузки полного родительского объекта без дублирующих дочерних элементов?

Ответы [ 4 ]

5 голосов
/ 01 июня 2011

Если вы отобразите Children и GrandChildren как установленные, вы можете избежать декартового произведения. Вы должны определить детей и внуков как коллекции:

public class Parent
{
    ...
    public virtual ICollection<Child> Children { get; set; }
    ...
}

public class Child
{
    ...
    public virtual ICollection<GrandChild> GrandChildren { get; set; }
    ...
}

А в отображении (используя FluentNHibernate):

public class ParentMapping : ClassMap<Parent>
{
    public ParentMapping()
    {
        ...
        HasMany(x => x.Children)
            .KeyColumn("ParentID")
            .Inverse
            .AsSet()
        ...
    }
}

public class ChildMapping : ClassMap<Child>
{
    public ChildMapping()
    {
        ...
        HasMany(x => x.GrandChildren)
            .KeyColumn("ChildID")
            .Inverse
            .AsSet()
        ...
    }
}
2 голосов
/ 02 июня 2011

Я смог использовать ответ здесь , используя QueryOver, он корректно загружает объекты при генерации эффективного SQL (выбирает для таблицы вместо одного огромного объединения).

1 голос
/ 25 августа 2012

Если вы используете Linq, вы можете упростить это с помощью:

int parentId = 1;
var p1 = session.Query<Parent>().Where(x => x.ParentId == parentId);

p1
.FetchMany(x => x.Children)
.ToFuture();

sess.Query<Child>()
.Where(x => x.Parent.ParentId == parentId);
.FetchMany(x => x.GrandChildren)
.ToFuture();

Parent p = p1.ToFuture().Single();

Подробное объяснение здесь: http://www.ienablemuch.com/2012/08/solving-nhibernate-thenfetchmany.html

1 голос
/ 01 июня 2011

Вы не можете сделать это с NHibernate (я не думаю, что вы можете сделать это и с EF4), так как ваш результат - декартово произведение.Вы получаете все результаты из всех таблиц.

NHibernate не знает, как отобразить результаты из обеих коллекций обратно в корень.Таким образом, для каждого ребенка вы получаете одинаковое количество внуков, а для каждого внука у вас одинаковое количество детей.

...