Подтвердить что ты не робот

NHibernate возвращает повторяющийся объект в дочерних коллекциях при использовании Fetch

Выполняя такой запрос (используя Nhibernate 2.1.2):

 ICriteria criteria = session.CreateCriteria<MyRootType>()
                .SetFetchMode("ChildCollection1", FetchMode.Eager)
                .SetFetchMode("ChildCollection2", FetchMode.Eager)
                .Add(Restrictions.IdEq(id));

Я получаю несколько дубликатов объектов в какой-то декартовой форме. Например. если ChildCollection1 имеет 3 элемента, а ChildColection2 имеет 2 элемента, тогда я получаю результаты с каждым элементом в ChildColection1, который дублируется, и каждый элемент из ChildColection2 трижды! Для меня это был момент WTF для меня...

Итак, как это сделать правильно?

  • Использует SetFetchMode, как это поддерживается только при указании одной коллекции?
  • Я просто использую его неправильно (я видел некоторые ссылки на трансформаторы результатов, но предполагал, что это будет проще).
  • Это что-то другое в NH3?

Update:

В соответствии с предложением Felice я попытался использовать трансформатор DistinctRootEntity, но это все равно возвращает дубликаты. Код:

ICriteria criteria = session.CreateCriteria<MyRootType>()
                .SetFetchMode("ChildCollection1", FetchMode.Eager)
                .SetFetchMode("ChildCollection2", FetchMode.Eager)
                .Add(Restrictions.IdEq(id));

 criteria.SetResultTransformer(Transformers.DistinctRootEntity);

 return criteria.UniqueResult<MyRootType>();
4b9b3361

Ответ 1

Вы можете выбрать отдельные результаты, указав SetResultsTransformer(Transformers.DistinctRootEntity);

Ответ 2

Здесь вы делаете декартивный продукт. Не. Вместо этого извлекает каждую коллекцию отдельно.

BTW: это не что-то конкретное NHibernate, то же самое относится к любому ORM на любой платформе или даже к чистому SQL без ORM. В общем случае вы не хотите получать N * M строк, когда вы можете выбрать N + M.

Ответ 3

Что вы собирали в своей коллекции? Если вы используете сумку, например, вы получите дубликаты. Вместо этого вы можете использовать набор, и вы не получите дубликатов.

Ответ 4

Я не использую NHibernate (скорее, обычный "Hibernate" ), но в версии Hibernate для Java вы можете определить коллекции "один-ко-многим" как списки или наборы. Если вы определяете их как Sets, вы не получите дубликатов. Удивительно, но это происходит без переопределения equals(). К сожалению, у меня такая же проблема, и мне нужны списки, поэтому я могу интегрироваться с Wicket, но не дублировать...

Ответ 5

Попробуйте использовать Futures:

ICriteria criteriaFuture1
    = session.CreateCriteria<MyRootType>()
        .SetFetchMode("ChildCollection1", FetchMode.Eager)
        .Add(Restrictions.IdEq(id))
        .SetResultTransformer(Transformers.DistinctRootEntity)
        .FutureValue<MyRootType>();
 ICriteria criteriaFuture2
    = session.CreateCriteria<MyRootType>()
        .SetFetchMode("ChildCollection2", FetchMode.Eager)
        .Add(Restrictions.IdEq(id))
        .SetResultTransformer(Transformers.DistinctRootEntity)
        .FutureValue<MyRootType>();

 return criteriaFuture1.Value;