NHibernate Cascade none 仍在更新相关实体
Posted
技术标签:
【中文标题】NHibernate Cascade none 仍在更新相关实体【英文标题】:NHibernate Cascade none still updating related entity 【发布时间】:2010-01-09 16:24:54 【问题描述】:然后我使用 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;
然后我将覆盖以下映射以明确设置从网页到网页类型的级联:
public class WebpageMap : IAutoMappingOverride<Webpage>
public void Override(AutoMapping<Webpage> mapping)
mapping.References(w => w.WebpageType).Cascade.None();
对于任何纯粹的 NHibernate 读者,这里是 fluent 生成的 xml 映射:
<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 的名称执行了更新。删除和保存(创建新)级联工作正常,不会级联。
我是否误解了级联和/或我的逻辑/测试有问题。
感谢任何帮助/建议。谢谢。
【问题讨论】:
【参考方案1】:如果您试图阻止您的应用意外更改 WebPageType 上的属性,我认为通过在映射中将 WebPageType 标记为 ReadOnly 来实现这一点会更容易、更安全。那么您就不需要通过处理其所有关联中的级联来保护它。
【讨论】:
干杯诺埃尔,我会试试看:)【参考方案2】:我认为这是对级联含义的误解。
在您的示例中,无论您将级联设置为什么,NHibernate 都会更新您的 WebPageType 的 Name 属性。如果您考虑一下,NHibernate 库将如何判断您是使用来自 WebPage 实例的关联来操作属性的值,还是“直接”完成?
NHibernate 中的级联设置告诉我们应该如何处理实体之间的关联,而不是如何处理每个实体内部的实际值。比如可以设置删除级联,当实体本身被删除时,会自动删除关联的实体。
Things 博客文章可能会让事情变得更清晰,或者至少可以作为某种参考:http://ayende.com/Blog/archive/2006/12/02/NHibernateCascadesTheDifferentBetweenAllAlldeleteorphansAndSaveupdate.aspx
【讨论】:
嗨 Liedman,我明白你在说什么,但是,如果我只保存网页对象,为什么 NH 还要保存与 WebpageType 的多对一关联?这不是一种级联保存吗?? 这是关于 NHibernate 工作方式的最常见错误之一。在 NHibernate 中,对持久对象的更改(即,您使用查询、获取/加载或仅使用保存从数据库加载到 ISession 的实例)自动保存到数据库中(除非您回滚交易)。来自文档:“事务性持久实例(即,由 ISession 加载、保存、创建或查询的对象)可以由应用程序操作,并且在刷新 ISession 时,对持久状态的任何更改都将保持不变”(刷新我自动,除非您另有说明。)【参考方案3】:您的存储库是做什么的?确保它不在网页类型上运行 saveorupdate。如果不是,那么我看不出这种行为有任何明显的解释。
【讨论】:
嗨,Brian,我的存储库只是保存网页而已。以上是关于NHibernate Cascade none 仍在更新相关实体的主要内容,如果未能解决你的问题,请参考以下文章