Ответ 1
Вы можете выбрать отдельные результаты, указав SetResultsTransformer(Transformers.DistinctRootEntity);
Выполняя такой запрос (используя 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 для меня...
Итак, как это сделать правильно?
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>();
Вы можете выбрать отдельные результаты, указав SetResultsTransformer(Transformers.DistinctRootEntity);
Здесь вы делаете декартивный продукт. Не. Вместо этого извлекает каждую коллекцию отдельно.
BTW: это не что-то конкретное NHibernate, то же самое относится к любому ORM на любой платформе или даже к чистому SQL без ORM. В общем случае вы не хотите получать N * M строк, когда вы можете выбрать N + M.
Что вы собирали в своей коллекции? Если вы используете сумку, например, вы получите дубликаты. Вместо этого вы можете использовать набор, и вы не получите дубликатов.
Я не использую NHibernate (скорее, обычный "Hibernate" ), но в версии Hibernate для Java вы можете определить коллекции "один-ко-многим" как списки или наборы. Если вы определяете их как Sets, вы не получите дубликатов. Удивительно, но это происходит без переопределения equals(). К сожалению, у меня такая же проблема, и мне нужны списки, поэтому я могу интегрироваться с Wicket, но не дублировать...
Попробуйте использовать 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;