псевдоним sql в словаре возвращает повторяющиеся результаты

#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. Добавлено примечание повторно: использование другой стратегии.