NHibernate 2.1.2 несохраненный временный экземпляр - PullRequest
1 голос
/ 13 июня 2011

Я прочитал много вопросов и ответов, но не смог найти решение своей проблемы. Проблема возникает, когда я мигрировал из NHibernate 1.2.1 в 2.1.2. У меня есть эта распространенная ошибка:

объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом. Тип: 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="..." />          
&lt/nhibernate>

Отображение основного класса CRResidence:

&lt?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" />
    &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/class>
&lt/hibernate-mapping> 

И один из классов по отношению ко многим к одному:

&lt?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" />
    &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/class>
&lt/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". У меня есть клиентская сторона, где я загружаю объект CRResidenceRegion, вызывая метод на стороне сервера в одном сеансе NHibernate. После загрузки сессия NHibernate закрывается. Объект на клиенте правильный, правильный идентификатор из базы данных и так далее. Затем объекту 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. В некоторых случаях работает нормально после определения каскадного стиля («none» работало так же, как и «all», где мне было нужно). Может быть проблема в файле конфигурации NHibernate.

Предыдущее определение проблемы: Когда я пытаюсь вставить или обновить экземпляр CRResidence, возникает ошибка о несохраненной временной ошибке. Экземпляр CRResidenceRegion полностью инициализирован, включая Id, поэтому проблем нет. Я реализовал метод Equal на Id. Я пытался очистить кэш, но это не помогло. Когда я изменяю каскад на сохранение-обновление, это работает, но записи CRResidenceRegion дублируются. Одно из решений заключается в том, что я считываю CRResidenceRegion из базы данных в том же сеансе (прокомментирован в коде ниже), прежде чем сохранить CRResidence, но это неприемлемо.

Кажется, что NHibernate, вероятно, потерял ссылку на CRResidenceRegion и думает, что он только что создан, но это не так.

Ответы [ 3 ]

1 голос
/ 13 июня 2011

Используйте метод Session.Load вместо Get, чтобы инициализировать сущность CRResidenceRegion. Это на самом деле не пойдет в базу данных, пока вы не получите доступ к любому из ее свойств.

...
residence.Region = session.Load<CRResidenceRegion>(residence.Region.Id);         
session.Update(residence);
trx.Commit();
...
0 голосов
/ 17 июня 2011

Я нашел решение своей проблемы. Проблема была в version_id, я добавил несохраненное значение в файл отображения CR_ResidenceRegion.

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

Я думаю, что они изменили значение по умолчанию unsaved-value.

Спасибо всем за помощь

0 голосов
/ 13 июня 2011

Это может быть потому, что оно пришло из другого эссиона.

Вместо этого попробуйте session.Merge().

...