NHibernate возвращает дубликат объекта в дочерних коллекциях при использовании Fetch - PullRequest
16 голосов
/ 17 января 2011

При выполнении запроса, подобного этому (используя 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?

Обновление:

Согласно предложению Феличе, я пытался использовать преобразователь 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>();

Ответы [ 5 ]

15 голосов
/ 17 января 2011

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

10 голосов
/ 17 января 2011

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

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

3 голосов
/ 18 марта 2011

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

3 голосов
/ 11 февраля 2011

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

2 голосов
/ 01 ноября 2013

Попробуйте использовать Фьючерсы :

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...