#nhibernate #nhibernate-mapping
#nhibernate #nhibernate-сопоставление
Вопрос:
У меня есть следующий класс
<class name="Product" table="Product">
<id name="ID" />
...
<map name="CustomFields" table="CustomFieldView">
<key column="RECORDID" />
<map-key column="CFName" type="String" />
<element column="CFValue" type="String" />
</map>
</class>
и SP для выбора продукта со словарем пользовательских полей
<sql-query name="GetProducts">
<return alias="p" class="Product" />
<return-join alias="cf" property="p.CustomFields" />
SELECT {p.*}, {cf.*}
FROM Product p
INNER JOIN CustomFieldView cf ON p.ID = cf.RECORDID
// WHERE
</sql-query>
когда я выбираю один продукт, например, ГДЕ ID = 1234, тогда он работает как ожидалось — возвращает один продукт с заполненным свойством словаря customFields.
Но когда я выбираю не один продукт, такой как ГДЕ идентификатор В (18780, 21642) или по другим критериям, тогда я получаю пользовательские поля Products duplicated ‘.Подсчитайте ‘ раз, например, 2 продукта, в каждом из которых по 20 пользовательских полей, затем 40 продуктов, в каждом из которых по 20 допустимых пользовательских полей.
Я что-то пропустил в сопоставлении?
Ответ №1:
Вы возвращаете a Cartesian product
и, следовательно, ваш продукт возвращается x раз для каждого пользовательского поля.
Чтобы обойти эту проблему, вам нужно будет использовать что-то вроде:-
var query = Session
.GetNamedQuery("GetProducts")
.SetResultTransformer(new DistinctRootEntityResultTransformer());
return query.List<Product>();
Пожалуйста, обратите внимание, что вы будете отправлять все данные по сети, а NHibernate будет выполнять работу на стороне отдельного клиента transformer (то есть веб-сервера или настольного приложения).
Я не уверен на 100%, будет ли заполнено обратное соединение, поскольку я никогда не делал ничего таким образом, вам нужно будет это протестировать.
редактировать Я думаю, что ваша стратегия выборки не совсем верна. Вам действительно нужен <sql-запрос …> Не могли бы вы использовать другую стратегию, например HQL
?
Комментарии:
1. Но такое сопоставление отлично работает, например, с <bag>, в настоящее время проблема только с <map> . Для меня это громоздко, я ищу более естественное решение. В любом случае большое спасибо!
2. Извините, я неправильно понял ваш вопрос. Однако я думаю, что ваша стратегия выборки не совсем верна. Вам действительно нужен
<sql-query ..
?3. Вы поняли меня совершенно правильно. Возможно, изменение на HQL поможет… Я вернусь с результатами теста. Спасибо
4. Я решил эту проблему с помощью HQL. Решение состоит в том, чтобы переписать SQL в HQL и не использовать явную ‘join fetch’ в HQL, просто добавьте fetch=’join’ в <map> . Я не нашел решения SQL, кроме использования DistinctTransformer, MultiQuery и Future (в моем случае это неприменимо к FireBird). Риппо, пожалуйста, опубликуй решение HQL в качестве ответа, я проверю его. Спасибо за вашу помощь!
5. Добавлено примечание повторно: использование другой стратегии.