【问题标题】:NHibernate 2.1.2 unsaved transient instanceNHibernate 2.1.2 未保存的瞬态实例
【发布时间】:2011-06-13 12:02:19
【问题描述】:

我已经阅读了很多问题和答案,但我找不到解决问题的方法。当我从 NHibernate 1.2.1 迁移到 2.1.2 时,会出现问题。 我有这个常见错误:

object 引用了一个未保存的瞬态实例 - 在刷新之前保存瞬态实例。类型:Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidenceRegion,实体:Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidenceRegion

NHibernate 配置: &lt休眠> &ltadd key="hibernate.show_sql" value="true" /> &ltadd key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" /> &ltadd key="方言" value="NHibernate.Dialect.MsSql2005Dialect" /> &ltadd key="proxyfactory.factory_class" value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle" /> &ltadd key="driver_class" value="NHibernate.Driver.SqlClientDriver" /> &ltadd key="connection.connection_string" value="..." /> &lt/休眠>

主类CRResidence的映射:

&lt?xml 版本="1.0" 编码="utf-8" ?> &lthibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false"> &ltclass name="Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidence, Mikro.FareOn.Modules.Cards.Interface" table="CR_Residence"> &ltid name="Id" column="id" type="Int64" access="nosetter.camelcase" unsaved-value="0"> &ltgenerator class="身份" /> &lt/id> &ltversion name="VersionId" column="version_id" type="Int64" /> &ltproperty name="IsDeleted" column="deleted" type="Boolean" not-null="true" /> &ltproperty name="Name" column="name" type="String" not-null="true" /> &ltmany-to-one name="Region" column="region_id" cascade="none" class="Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidenceRegion, Mikro.FareOn.Modules.Cards.Interface"/> &ltproperty name="Postcode" column="postcode" type="String" not-null="true" /> &ltmany-to-one name="Country" column="residence_country_id" cascade="none" class="Mikro.FareOn.TransportOperator.Interface.BEC.TOResidenceCountry, Mikro.FareOn.TransportOperator.Interface"/> &lt/类> &lt/hibernate-mapping>

与多对一相关的类之一:

&lt?xml 版本="1.0" 编码="utf-8" ?> &lthibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false"> &ltclass name="Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidenceRegion, Mikro.FareOn.Modules.Cards.Interface" table="CR_ResidenceRegion" > &ltid name="Id" column="id" type="Int64" access="nosetter.camelcase" unsaved-value="0"> &ltgenerator class="身份" /> &lt/id> &ltversion name="VersionId" column="version_id" type="Int64" /> &ltproperty name="Name" column="name" type="String" not-null="true" /> &ltproperty name="IsDeleted" column="deleted" type="Boolean" not-null="true" /> &lt/类> &lt/休眠映射>

CRResidenceRegion 类的实现:

[可序列化] public class CRResidence : BussinesEntityComponentBase //这是一个类,它实现了Equals并定义了Id、VersionId、IsDeleted { 字符串名称; 字符串邮政编码; CRResidenceRegion 区域; TOResidenceCountry国家; #region 获取器/设置器 /// /// 纳泽夫米斯塔 /// 公共字符串名称 { 获取{返回此名称; } 设置 { this.name = value; } } /// /// 地区 /// 公共 CRResidenceRegion Region { 得到 { 返回这个.region; } 放 { this.region = 值; } } /// /// 统计 /// 公共 TOResidenceCountry Country { 得到 { 返回这个.country; } 放 { 这个国家=价值; } } /// /// PSC /// 公共字符串 邮政编码 { 得到{返回this.postcode; } 设置 { this.postcode = value; } } 公共字符串 PostcodeAndName { get { return String.Format("{0} - {1}", Postcode, Name); } } 公共字符串 NameAndPostcode { get { return String.Format("{1} - {0}", Postcode, Name); } } #endregion /// /// Konstruktor objektu rezidence /// 公共 CRResidence() : 根据() { } }

我尝试了所有类型的级联,但任何级联都无法正常工作。但就我而言,我更喜欢 cascade = "none"。 我有客户端,通过在一个 NHibernate 会话中调用服务器端的方法来加载对象 CRResidenceRegion。加载 NHibernate 会话后关闭。客户端上的对象是正确的,数据库中的正确 ID 等等。然后给CRResidence对象赋值CRResidenceRegion对象。 然后在服务器端调用方法:

使用 (PersistenceSession session = Registrator.OpenSession()) { ITransaction trx = session.BeginTransaction(); 尝试 { session.Update(居住地); //residence.Region = (CRResidenceRegion)session.Get(typeof(CRResidenceRegion),residence.Region.Id); //residence.Country = (TOResidenceCountry)session.Get(typeof(TOResidenceCountry),residence.Country.Id); trx.Commit(); log.Debug("CRResidence 更新。"); 返还居住地; } 捕捉(例外前) ………… }

我有很多这样的对象,当我迁移到 NHibernate 2.1.2 时出现了这个问题。在某些情况下,在定义级联样式后效果很好(“无”和“全部”一样有效,我需要)。可能是NHibernate的配置文件有问题。

之前的问题定义: 当我尝试插入或更新 CRResidence 的实例时,出现有关未保存的瞬态错误的错误。 CRResidenceRegion的Instance完全初始化了,包括Id,所以没有问题。我在 Id 上实现了 Equal 方法。我试图清除缓存,但没有帮助。当我将级联更改为保存更新时,它可以工作,但是 CRResidenceRegion 的记录是重复的。一种解决方案是在保存 CRResidence 之前,我在同一会话中从数据库中读取 CRResidenceRegion(在下面的代码中注释),但这是不可接受的。

似乎 NHibernate 已经失去了对 CRResidenceRegion 的引用,并认为它是新创建的,但事实并非如此。

【问题讨论】:

    标签: c# nhibernate many-to-one transient


    【解决方案1】:

    使用 Session.Load 方法而不是 Get 来初始化 CRResidenceRegion 实体。除非您访问它的任何属性,否则这实际上不会进入数据库。

    ...
    residence.Region = session.Load<CRResidenceRegion>(residence.Region.Id);         
    session.Update(residence);
    trx.Commit();
    ...
    

    【讨论】:

    • 它不起作用,因为session.Load必须在更新之前,但无论如何它和session.Get一样。这会起作用,但我认为这不是正确的解决方案。但我谢谢你。
    • @user,这是正确的解决方案。 Session.Load 与 Session.Get 完全不同。 Session.Get 将始终与数据库背道而驰。而 Session.Load 只会在需要时与数据库发生冲突。在您的情况下,您只需要从会话加载一个非瞬态实体。您不需要从数据库中获取它,因此您可以使用 Load 方法。
    • 是的,但我不能使用它,因为我必须更改大约 500 个函数,包括映射集合。我必须返回 NHibernate 1.2.1 或停止使用 NHibernate。谢谢。
    【解决方案2】:

    这可能是因为它来自另一个会话。

    改用session.Merge()

    【讨论】:

    • 你能用你如何检索对象和修改它来更新问题吗?
    • 另外,您是否尝试更改映射中的cascade 属性?
    • 是的,我已经尝试了所有类型的级联映射,我也尝试更多地解释问题。
    【解决方案3】:

    我找到了解决问题的方法。 问题出在 version_id 中,我在 CR_ResidenceRegion 的映射文件中添加了一个未保存的值。

    &ltversion name="VersionId" column="version_id" type="Int64" unsaved-value="0" />

    我认为他们更改了 unsaved-value 的默认值。

    感谢大家的帮助

    【讨论】:

      猜你喜欢
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 2014-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多