NHibernate Cascade никто не обновляет связанный объект

Затем я использую Fluent NHibernate и его функцию автоматического сопоставления для сопоставления следующих упрощенных классов POCO:

public class Webpage
{    
public virtual int Id { get; set; }    
public virtual string UrlIdentifier { get; set; }    
public virtual WebpageType WebpageType { get; set; }    
}

public class WebpageType
{    
public virtual int Id { get; set; }    
public virtual string Name { get; set; }       
}

Затем я переопределяю следующее сопоставление, чтобы явно не устанавливать каскадирование с веб-страницы на WebpageType:

public class WebpageMap : IAutoMappingOverride<Webpage>
{
    public void Override(AutoMapping<Webpage> mapping)
    {
        mapping.References(w => w.WebpageType).Cascade.None();    
    }
}

Для любых читателей pur NHibernate, вот xml-сопоставления, созданные fluent:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
  <class xmlns="urn:nhibernate-mapping-2.2" name="EveryPage.Core.Domain.Webpage, EveryPage.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Webpage`">
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" unsaved-value="0">
      <column name="Id" />
      <generator class="identity" />
    </id>
    <property name="UrlIdentifier" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="UrlIdentifier" />
    </property>
    <many-to-one cascade="none" class="EveryPage.Core.Domain.WebpageType, EveryPage.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="WebpageType">
      <column name="WebpageType_id" />
    </many-to-one>    
  </class>
</hibernate-mapping>


<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
  <class xmlns="urn:nhibernate-mapping-2.2" name="EveryPage.Core.Domain.WebpageType, EveryPage.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`WebpageType`">
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" unsaved-value="0">
      <column name="Id" />
      <generator class="identity" />
    </id>
    <property name="Name" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Name" />
    </property>
  </class>
</hibernate-mapping>

Проблема возникает, когда я проверяю, что обновления не передаются каскадом на WebpageType через веб-страницу, в основном они это делают !!

У меня есть следующий тест:

    [Test]
    public void Assert_SaveOrUpdate_On_Webpage_Does_Not_Cascade_Update_To_WebpageType()
    {
        // Get the existing webpage.
        webpage = _webpageRepository.Get("~/testwebpage1.aspx");

        // Update the WebpageType.
        const string webpageTypeName = "qwerty test";
        webpage.WebpageType.Name = webpageTypeName;

        // Save the changes.
        Assert.DoesNotThrow(() => _webpageRepository.SaveOrUpdate(webpage));

        // We need to flush the changes to the store for it to execute the changes.
        Assert.DoesNotThrow(() => NHibernateSession.Current.Flush());

        // Remove the webpage and tag from the level 1 cache so we force a trip to the store on our next check.
        NHibernateSession.Current.Evict(webpage);

        //  Check that the webpageType has not been updated.
        webpageType = _webpageTypeRepository.Get(webpageType.Id);
        Assert.AreNotEqual(webpageTypeName, webpageType.Name);
    }

Вышеупомянутый тест заключен в глобальную транзакцию.

Тест не проходит, и NHibernate выполняет обновление имени соответствующего WebpageType. Каскады удаления и сохранения (создания нового) работают правильно и не каскадируются.

Я неправильно понял каскад и / или возникла проблема с моей логикой / тестом.

Любая помощь / совет приветствуются. Спасибо.


person j3ffb    schedule 09.01.2010    source источник


Ответы (3)


Если вы пытаетесь помешать вашему приложению случайно изменить свойства в WebPageType, я думаю, было бы проще и безопаснее добиться этого, пометив WebPageType как ReadOnly в сопоставлении. Тогда вам не нужно будет защищать его, обрабатывая каскадирование во всех его ассоциациях.

person Noel Kennedy    schedule 11.01.2010
comment
Ура, Ноэль, я попробую :) - person j3ffb; 12.01.2010

Я думаю, что это неправильное понимание того, что такое каскадирование.

В вашем примере NHibernate обновит свойство Name вашего WebPageType независимо от того, что вы установили для каскадирования. Если задуматься, как библиотека NHibernate сообщит, манипулируете ли вы значением свойства, используя ассоциацию из экземпляра WebPage, или это делается «напрямую»?

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

Сообщение в блоге «Вещи» может прояснить ситуацию или, по крайней мере, работать как своего рода справочник: http://ayende.com/Blog/archive/2006/12/02/NHibernateCascadesTheDifferentBetweenAllAlldeleteorphansAndSaveupdate.aspx

person Liedman    schedule 11.01.2010
comment
Привет, Лидман, я понимаю, о чем вы говорите, однако, если я сохраню только объект веб-страницы, почему NH также выполняет сохранение связи многие-к-одному с WebpageType? Разве это не каскадное спасение ??? - person j3ffb; 12.01.2010
comment
Это одна из самых распространенных ошибок в работе NHibernate. В NHibernate изменения постоянных объектов (то есть экземпляров, которые вы загрузили в ISession из БД с помощью запроса, получения / загрузки или просто сохраняли с помощью сохранения) автоматически сохраняются в базе данных (если вы не откатываете перевод). Из документации: постоянные экземпляры транзакций (т. Е. Объекты, загруженные, сохраненные, созданные или запрошенные ISession) могут управляться приложением, и любые изменения в постоянном состоянии будут сохраняться при сбросе ISession (очистить i автоматически, если вы не укажете иное. .) - person Liedman; 12.01.2010

Что делает ваш репозиторий? Убедитесь, что он не запускает сохранение или обновление для типа веб-страницы. Если это не так, то я не вижу очевидного объяснения такому поведению.

person Brian O'Connell    schedule 09.01.2010
comment
Привет, Брайан, нет, мой репозиторий просто сохраняет веб-страницу. - person j3ffb; 12.01.2010