首页 文章

NHibernate 2.1.2未保存的瞬态实例

提问于
浏览
1

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

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

NHibernate configuration:
&ltnhibernate>
          &ltadd key="hibernate.show_sql" value="true" />
          &ltadd key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
          &ltadd key="dialect" 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="..." />          
</nhibernate>

主类CRResidence的映射:

<?xml version="1.0" encoding="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="identity" />
    </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"/>
  </class>
</hibernate-mapping>

和多对一关系中的一个:

<?xml version="1.0" encoding="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="identity" />
    </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" />
  </class>
</hibernate-mapping>

CRResidenceRegion类的实现:

[Serializable]
    public class CRResidence : BussinesEntityComponentBase //this is class, which implements Equals and define Id, VersionId, IsDeleted
    {
    string name;
        string postcode;
    CRResidenceRegion region;
    TOResidenceCountry country;

    #region Getters/Setters

    /// 
    /// Nazev mista
    /// 
    public string Name
    {
      get { return this.name; }
      set { this.name = value; }
    }
    /// 
    /// Region
    /// 
    public CRResidenceRegion Region
    {
      get
      {
        return this.region;
      }
      set
      {
        this.region = value;
      }
    }
    /// 
    /// Stát
    /// 
    public TOResidenceCountry Country
    {
      get
      {
        return this.country;
      }
      set
      {
        this.country = value;
      }
    }
    /// 
    /// PSC
    /// 
    public string Postcode
    {
      get { return this.postcode; }
      set { this.postcode = value; }
    }
    public string PostcodeAndName
    {
      get { return String.Format("{0} - {1}", Postcode, Name); }
    }
    public string NameAndPostcode
    {
      get { return String.Format("{1} - {0}", Postcode, Name); }
    }
    #endregion
    /// 
    /// Konstruktor objektu rezidence
    /// 
    public CRResidence()
      : base()
    {
    }    
}

我尝试了所有类型的级联,但任何级联都无法正常工作 . 但在我的场合,我更喜欢cascade =“none” . 我有客户端,在一个NHibernate会话中通过调用服务器端的方法加载对象CRResidenceRegion . 加载后,NHibernate会话关闭 . 客户端上的对象是正确的,来自数据库的正确ID等等 . 然后向CRResidence对象分配CRResidenceRegion对象 . 然后它在服务器端被称为方法:

using (PersistenceSession session = Registrator.OpenSession())
{
        ITransaction trx = session.BeginTransaction();
        try
        {          
          session.Update(residence);
          //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 updated.");
          return residence;
        }
        catch (Exception ex)
............
      }

我有很多像这样的对象,当我迁移到NHibernate 2.1.2时出现了这个问题 . 在某些情况下定义级联风格后工作正常(“无”工作以及“所有”,我需要的地方) . 可能是NHibernate配置文件中的问题 .

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

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

3 回答

  • 0

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

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

    这可能是因为它来自另一个激情 .

    请尝试使用 session.Merge() .

  • 0

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

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

    我认为他们改变了unsaved-value的默认值 .

    谢谢大家的帮助

相关问题