Я прочитал много вопросов и ответов, но не смог найти решение своей проблемы. Проблема возникает, когда я мигрировал из NHibernate 1.2.1 в 2.1.2.
У меня есть эта распространенная ошибка:
объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом. Тип: Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidenceRegion, Объект: Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidenceRegion
NHibernate configuration:
<nhibernate>
<add key="hibernate.show_sql" value="true" />
<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
<add key="dialect" value="NHibernate.Dialect.MsSql2005Dialect" />
<add key="proxyfactory.factory_class" value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle" />
<add key="driver_class" value="NHibernate.Driver.SqlClientDriver" />
<add key="connection.connection_string" value="..." />
</nhibernate>
Отображение основного класса CRResidence:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
<class name="Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidence, Mikro.FareOn.Modules.Cards.Interface" table="CR_Residence">
<id name="Id" column="id" type="Int64" access="nosetter.camelcase" unsaved-value="0">
<generator class="identity" />
</id>
<version name="VersionId" column="version_id" type="Int64" />
<property name="IsDeleted" column="deleted" type ="Boolean" not-null="true" />
<property name="Name" column="name" type="String" not-null="true" />
<many-to-one name="Region" column="region_id" cascade="none" class="Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidenceRegion, Mikro.FareOn.Modules.Cards.Interface"/>
<property name="Postcode" column="postcode" type="String" not-null="true" />
<many-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" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
<class name="Mikro.FareOn.Modules.Cards.Interface.BEC.CRResidenceRegion, Mikro.FareOn.Modules.Cards.Interface" table="CR_ResidenceRegion" >
<id name="Id" column="id" type="Int64" access="nosetter.camelcase" unsaved-value="0">
<generator class="identity" />
</id>
<version name="VersionId" column="version_id" type="Int64" />
<property name="Name" column="name" type="String" not-null="true" />
<property 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".
У меня есть клиентская сторона, где я загружаю объект 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 и думает, что он только что создан, но это не так.