NHibernate 3.x удаляет дочерние объекты при объединении подкачки LINQ, множества ко многим и выборки после выбора - PullRequest
9 голосов
/ 24 мая 2011

Наше приложение имеет концепцию истории и концепцию теги . К истории может быть применено множество тегов, а тег может быть применен ко многим историям, что делает отношения многие ко многим. Две таблицы, истории и теги соединены с третьим, StoriesToTags .

Соответствующие части файлов сопоставления:

Вот отображение из Story в Tag :

<class name="Story" table="Stories">
  ...
  <set fetch="subselect" name="Tags" table="StoriesToTags">
    <key>
      <column name="StoryId" />
    </key>
    <many-to-many class="Tag">
      <column name="TagId" />
    </many-to-many>
  </set>
</class>

И обратная зависимость от Метка до История :

<class name="Tag" table="Tags">
  ...
  <set fetch="subselect" inverse="true" name="Stories" table="StoriesToTags">
    <key>
      <column name="TagId" />
    </key>
    <many-to-many class="Story">
      <column name="StoryId" />
    </many-to-many>
  </set>
</class>

Как видите, мы используем стратегию выборки subselect , чтобы избежать проблемы запроса N + 1. Все отлично работает, пока вы не попытаетесь отобразить результат с помощью LINQ:

IQueryable<Story> stories = GetStories(...).TakePage(pageNumber, pageSize);

После выполнения этого запроса NHibernate удаляет отношения (записи в StoriesToTags ) для всех историй, которые не были загружены в запросе. Кажется, что это происходит только в том случае, если теги загружены специально (то есть подзапуск срабатывает). Отношения не удаляются, если мы переключаемся на присоединение или выбор стратегии выборки, но это приводит к выполнению N + 1 запросов.

Мое лучшее предположение заключается в том, что NHibernate считает, что теги были осиротевшими, но мы не установили каскадов в коллекциях. Кроме того, насколько я могу судить, установка каскада не имеет никакого эффекта.

Этот процесс прекрасно работал под NHibernate 2.x и NHibernate.Linq. Мы не видели проблемы с удалением, пока не перешли на NHibernate 3.x, в который встроена поддержка LINQ. Я не уверен, что это что-то меняет, но для этого мы используем SQL Server с ключами идентификации.

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

Редактировать: Еще одна интересная информация. Если вы позвоните session.IsDirty() до закрытия сеанса, проблема не возникнет. Я подозреваю, что это потому, что изменения коллекции не сохраняются между сбросами, но я не могу достаточно хорошо расшифровать источник NHibernate, чтобы знать наверняка.

Ответы [ 2 ]

1 голос
/ 01 августа 2011

если вы настроили отображение субъекта: Cascade.None () это прекратит удаление чего-либо еще, кроме объекта.

Это может помочь: http://ayende.com/blog/1890/nhibernate-cascades-the-different-between-all-all-delete-orphans-and-save-update

0 голосов
/ 24 мая 2011

Можете ли вы дать нам некоторое представление о том, что вы пытаетесь достичь здесь? Я никогда не экспериментировал с указанной выборкой «многие ко многим», но мне кажется, что это как-то связано с явным каскадом = все для многих ко многим.

...