Подтвердить что ты не робот

Руководство по применению каскада NHibernate Definitive

Существуют ли какие-либо интернет-ресурсы, которые имеют исчерпывающее руководство ко всем параметрам каскада для NHibernate, которые будут включать примеры структуры классов, HBM и последствия действий с каждой из настроек каскада для всех отношений с NH.

Также было бы полезно, если бы были примеры для общих ассоциаций, которые можно было бы сделать наиболее правильным образом, например, настроить таблицу состояний, в которой вы никогда не закончите каскад, удалив состояние или удалив объект, у которого есть созданныйBy Пользовательское свойство никогда не удалит пользователя в каскаде и т.д.

4b9b3361

Ответ 1

Ниже приведена ссылка на Java Hibernate http://docs.jboss.org/hibernate/stable/core/manual/en-US/html/objectstate.html#objectstate-transitive для NHiberate 3.0 (то есть текущая строка svn).

Для каждой основной операции сеанса NHibernate, включая Persist(), Merge(), SaveOrUpdate(), Delete(), Lock(), Refresh(), Evict(), Replicate() - есть соответствующий каскад стиль. Соответственно, каскадные стили называются persist, merge, save-update, delete, lock, refresh, evict, replicate. Каскадный стиль для Save() и Update() - это save-update; для SaveAndUpdateCopy() это слияние; и для PersistOnFlush() он сохраняется. И удалить это псевдоним для удаления.

Если вы хотите, чтобы операция была каскадирована вдоль ассоциации, вы должны указать это в документе сопоставления. Например:

<one-to-one name="person" cascade="persist"/>

Каскадные стили мои сочетаются:

<one-to-one name="person" cascade="persist,delete,lock"/>

Вы можете использовать cascade = "all", чтобы указать, что все операции должны быть каскадированы вдоль ассоциации. По умолчанию cascade = "none" указывает, что никакие операции не должны каскадироваться.

Специальный каскадный стиль, delete-orphan, применяется только к ассоциациям "один ко многим" и указывает, что операция Delete() должна применяться к любому дочернему объекту, который удален из ассоциации. И all-delete-orphan - это то же самое, что и все, delete-orphan.

Рекомендации:

  • Как правило, не имеет смысла включать каскад в < много-к-одному > или < много-ко-многим > ассоциация. Каскад часто полезен для < один к одному > и < один-ко-многим > ассоциации.
  • Если срок жизни дочернего объекта ограничен продолжительностью жизни родительского объекта, сделайте его объектом жизненного цикла, указав cascade = "all-delete-orphan".
  • В противном случае вам может не понадобиться каскад. Но если вы думаете, что часто будете работать с родителем и детьми вместе в одной и той же транзакции, и вы хотите сохранить себе некоторую типизацию, рассмотрите возможность использования cascade = "persist, merge, save-update".

Сопоставление ассоциации (либо однозначной ассоциации, либо коллекции) с cascade = "all" обозначает ассоциацию как отношение родительского/дочернего стиля, где сохранение/обновление/удаление родительского объекта приводит к сохранению/обновлению/удалению ребенка или детей. Ребенок, который не получает ответа от своего родителя, автоматически не удаляется, за исключением случая с < one-to-many > ассоциация, сопоставленная с каскадом = "delete-orphan". Точная семантика каскадных операций для отношения родительский/дочерний выглядит следующим образом:

  • Если родительский объект передан в Persist(), все дети передаются в Persist()
  • Если родительский объект передан в Merge(), все дочерние элементы передаются в Merge()
  • Если родительский элемент передан в Save(), Update() или SaveOrUpdate(), все дочерние элементы передаются в SaveOrUpdate()
  • Если переходный или отдельный дочерний объект ссылается постоянным родителем, он передается в SaveOrUpdate()
  • Если родитель удален, все дети передаются в Delete()
  • Если дочерние элементы разыменовываются постоянным родителем, ничего особенного не происходит - приложение должно явно удалять дочерний элемент, если необходимо, если только cascade = "delete-orphan", и в этом случае ребенок-сироту удаляется.

Ответ 2

Это может быть очевидный совет, но я бы предложил просмотреть старый пост, сделанный Ayende. Быстрый search для NHibernate и каскада на его сайте показал несколько интересных сообщений. Однако они могут быть слишком скудными для ваших нужд.

Даже если это не интернет-ресурс как таковой, я бы также рекомендовал NHibernate в действии. Он подробно рассматривает каскады в главах 3, 4 и 6. Книга нацелена на NHibernate 1.2. Однако я верю, что появится новое издание книги, ориентированное на выпуск NHibernate 3.0; возможно, стоит обратить внимание.

Насколько мне хотелось бы видеть окончательное руководство к каскадам, я его не видел. Возможно, вы могли бы подытожить некоторые из сообщений в блоге, где обсуждаются каскады с вашим собственным сообщением в вашем собственном блоге.

Ответ 3

Я не знаю никакого "окончательного" руководства, но лучший ресурс, который я знаю, - это сообщение в блоге от Айенде, который является одним из окончательных гуру в NHibernate:

NHibernate Cascades: разные между всеми, все-удалить-сироты и сохранить-обновить

Для меня я использую только cascade="none" и cascade="all". all-delete-orphan иногда является опцией. Все остальное подозрительно. Например, почему я должен неявно создавать экземпляр, потому что он ссылается, когда он живет дольше, чем содержащий объект? Для меня есть только две ситуации: либо объект является зависимым, либо независимым.

Ответ 4

Принятый ответ объясняет это в деталях файлами HBM. Этот ответ охватывает то же самое с Mapping By Code. Они почти одинаковы; только что сопоставлены с их строками HBM.

Форма статьи Айенде хорошо объясняет это:

  • нет - не делайте никаких каскадов, пусть пользователи сами их обрабатывают.
  • save-update - когда объект сохраняется/обновляется, проверяйте ассоциации и сохраняйте/обновляйте любой объект, который требует его (включая сохранение/обновление ассоциаций в сценарии "многие ко многим").
  • удалить - при удалении объекта удаляются все объекты в ассоциации.
  • delete-orphan - при удалении объекта удаляются все объекты в ассоциации. В дополнение к этому, когда объект удаляется из ассоциации и не связан с другим объектом (осиротевшим), также удаляйте его.
  • все - при сохранении/обновлении/удалении объекта проверьте ассоциации и сохраните/обновите/удалите все найденные объекты.
  • all-delete-orphan - когда объект сохраняется/обновляется/удаляется, проверяйте ассоциации и сохраняйте/обновляйте/удаляйте все найденные объекты. В дополнение к этому, когда объект удаляется из ассоциации и не связан с другим объектом (осиротевшим), также удаляйте его.

Кроме того, этот вопрос объясняет несколько внутренних реализаций Cascade.

[Flags]
public enum Cascade
{
    None = 0,
    Persist = 2,
    Refresh = 4,
    Merge = 8,
    Remove = 16,
    Detach = 32,
    ReAttach = 64,
    DeleteOrphans = 128,
    All = 256,
}
private static IEnumerable<string> CascadeDefinitions(this Cascade source)
{
    if (source.Has(Cascade.All))
    {
        yield return "all";
    }
    if (source.Has(Cascade.Persist))
    {
        yield return "save-update, persist";
    }
    if (source.Has(Cascade.Refresh))
    {
        yield return "refresh";
    }
    if (source.Has(Cascade.Merge))
    {
        yield return "merge";
    }
    if (source.Has(Cascade.Remove))
    {
        yield return "delete";
    }
    if (source.Has(Cascade.Detach))
    {
        yield return "evict";
    }
    if (source.Has(Cascade.ReAttach))
    {
        yield return "lock";
    }
    if (source.Has(Cascade.DeleteOrphans))
    {
        yield return "delete-orphan";
    }
}

Обратите внимание, что Cascade.All не включает в себя Cascade.DeleteOrphans. В этом случае вам может понадобиться включить его, используя Cascade.All | Cascade.DeleteOrphans.

В качестве альтернативы вы можете использовать метод расширения Include Cascade.All.Include(Cascade.DeleteOrphans).

В сочетании с Cascade вам может потребоваться также изучить Inverse; это указывает на владельца ассоциации. Для получения дополнительной информации см. этот вопрос и этот ответ.