NHibernate Cascade nenhum ainda atualizar entidade relacionada
-
19-09-2019 - |
Pergunta
Estou em seguida, usando Fluent NHibernate e sua característica mapeamento automático para mapear as seguintes classes POCO simplificadas:
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; }
}
Estou em seguida, substituindo o seguinte mapeamento para definir explicitamente nenhuma cascata da página Web para WebpageType:
public class WebpageMap : IAutoMappingOverride<Webpage>
{
public void Override(AutoMapping<Webpage> mapping)
{
mapping.References(w => w.WebpageType).Cascade.None();
}
}
Para todos os leitores NHibernate pur, aqui estão os mapeamentos XML produzidos pela fluente:
<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>
O problema surge quando eu testar se as atualizações não cascata para WebpageType via página web, basicamente, eles fazem !!
Eu tenho o seguinte teste:
[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);
}
O teste acima é envolto em uma transação global.
O teste falha e NHibernate faz executar uma atualização para o Nome do WebpageType relacionado. As cascatas apagar e guardar (criar novo) funcionam corretamente e não fazer em cascata.
Have I missunderstood cascata e / ou há um problema com a minha lógica / teste.
Qualquer ajuda / aconselhamento é apreciado. Obrigado.
Solução
Se você está tentando parar a sua aplicação alterem acidentalmente propriedades em WebPageType, eu acho que seria mais fácil e mais seguro para atingir esse marcando WebPageType como ReadOnly no mapeamento. Então você não vai precisar para protegê-lo através de manipulação em cascata em todas as suas associações.
Outras dicas
Eu acho que este é um mal-entendido do que em cascata meios.
No seu exemplo, NHibernate irá atualizar a propriedade de nome de vocês não WebPageType independentemente da configuração em cascata para. Se você pensar sobre isso, como é que a biblioteca tell NHibernate se você está manipulando o valor da propriedade usando a associação da instância página web, ou se ele é feito "directamente"?
As definições para cascata em NHibernate conta como associações entre entidades devem ser manipulados, e não como o valor real dentro de cada entidade é tratado. Por exemplo, você pode definir exclusão em cascata, o que excluirá automaticamente entidades associadas quando a entidade em si é excluído.
As coisas blog pode tornar as coisas um pouco mais claro, ou pelo menos o trabalho como uma espécie de referência: http://ayende.com/Blog/archive/2006/12/02/NHibernateCascadesTheDifferentBetweenAllAlldeleteorphansAndSaveupdate.aspx
O que o seu repositório de fazer? Certifique-se de não executar um saveOrUpdate na webpagetype. Se não for, então eu não vejo qualquer explicação óbvia para este comportamento.