Hibernate version: 2.0
Hey guys,
I've just created a Two way relational mapping between two objects (one to many with bag (IList<Child>) and many-to-one object in other mapping)
Now i'm getting the error :
Illegal attempt to associate a collection with two open sess
before i've added the IList in my object (and mapping), i did not get this error.
Here's my code
ERROR OCCURS ON object obj = base.PerformSaveOrUpdate(evt); (in Custom SaveEventListener)
Mapping
Parent:
Code:
<bag name="LookupOutputs" inverse="true" cascade="all-delete-orphan" lazy="false">
<key column="KbaID" />
<one-to-many class="ET.Deap.Common.Model.LookupOutput" not-found="exception"/>
</bag>
Child:
Code:
<many-to-one name="KbaExtended"
cascade="none"
column="KbaId"
class="ET.Deap.Common.Model.KbaExtended"
lazy="false"
not-found="exception"
not-null="true" />
Code between sessionFactory.openSession() and session.close():Code:
ITransaction tx2 = session2.BeginTransaction();
try
{
// when calling the saveOrUpdate method of the session,
// NHibernate starts doing his work.
// through NHibernate we have connected eventlisteners that check every object before the action occurs.
// check NHibernateEventListeners
Log.Info(" Starting Save Or Update in the NHibernate Session");
session2.SaveOrUpdate(ent); // update object in database of the specified project through sessionfactory
tx2.Commit();
}
Custom SaveOrUpdate EventListener : ERROR OCCURS ON object obj = base.PerformSaveOrUpdate(evt);
Code:
/// <summary>
/// When performing ANY save or an update of an entity, this will first be executed
/// </summary>
/// <param name="evt"></param>
/// <returns></returns>
protected override object [b]PerformSaveOrUpdate(NHibernate.Event.SaveOrUpdateEvent evt)[/b]
{
Log.EnterMethod();
Log.Info(" -- objectType: " + evt.Entity.GetType().FullName);
Log.Info(" -- object: " + evt.Entity.ToString());
IDatabaseEntity ent = evt.Entity as IDatabaseEntity;
ent.FormatValuesForSave();
if (ent is DataObject)
{
Log.Info(" - Entity is a DataObject (basetype). Process DataObject starting now");
ProcessDataObjectBeforeSaveOrUpdate(ent as DataObject, evt.Session, evt.Entry == null);
}
Log.Info(" - Save the object through NHibernate in database (session is in event)");
object obj = base.PerformSaveOrUpdate(evt);
if (obj is DataObject)
{
Log.Info(" - Entity is a DataObject (basetype). format the object for use");
DataObject dataObject = obj as DataObject;
dataObject.FormatValuesForUse();
dataObject.LoadFromDatabaseComplete = true;
}
Log.LeaveMethod();
return obj;
}
/// <summary>
/// Do DataObject related things
/// </summary>
/// <param name="dataObject">dataobject that is going to be saved</param>
/// <param name="session">the current opened session</param>
/// <param name="useChangeLog">if the changelog has to be saved or not</param>
[b] private void ProcessDataObjectBeforeSaveOrUpdate(DataObject dataObject, ISession session, bool useChangeLog)[/b]
{
Log.EnterMethod();
Log.Info(" -- useChangelog: " + useChangeLog.ToString());
Log.Info(" -- " + dataObject.GetType().Name + " object: " + dataObject.ToString());
Log.Info(" - fill in user and date of save");
dataObject.LoadFromDatabaseComplete = false;
dataObject.ModifiedOn = DateTime.Now;
dataObject.ModifiedBy = "user"; // get out of userUtils
// check if the object is a new object or this is an update of an existing object
// if there is an id --> update, new object will return null
object id = ReturnIdOrNull(dataObject);
if (useChangeLog && id != null) // if there is an Id --> update so changelog (new object = null)
{
Log.Info(" - start to create a changelog to save to the database");
ValidationResult vr = new ValidationResult(false);
Log.Info(" - get object like it exists in the database before this save");
DataObject previousObject = (DataObject)session.Get(dataObject.GetType(), id);
// fill the changelog
ChangeLog chg = new ChangeLog();
chg.Blob = previousObject.ToBlob();
chg.DatabaseAction = DatabaseAction.Update;
chg.ModifiedBy = dataObject.ModifiedBy;
chg.ModifiedOn = dataObject.ModifiedOn;
chg.ObjectId = id.ToString();//dataObject.GetType().InvokeMember("Id", System.Reflection.BindingFlags.GetProperty, null, dataObject, null).ToString();
chg.ObjectType = (DatabaseObjectType)Enum.Parse(typeof(DatabaseObjectType), dataObject.GetType().Name.ToString());
chg.ObjectVersion = dataObject.Version;
chg.NameValuePairs = dataObject.NameValuePairs;
// get previousObject out of session. Two objects with the same type and id will cause problems
session.Evict(previousObject);
try
{
// save it
session.Save(chg);
}
catch
{
// handle exception in upper level. there we can give information back to the user
throw;
}
}
else
{
dataObject.CreatedBy = "user"; // get out of userUtils
dataObject.CreatedOn = dataObject.ModifiedOn;
}
Log.LeaveMethod();
}
Full stack trace of any exception that occurs: at NHibernate.Collection.AbstractPersistentCollection.SetCurrentSession(ISessionImplementor session)
at NHibernate.Event.Default.OnUpdateVisitor.ProcessCollection(Object collection, CollectionType type)
at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Object value, IType type)
at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Int32 i, Object[] values, IType[] types)
at NHibernate.Event.Default.AbstractVisitor.ProcessEntityPropertyValues(Object[] values, IType[] types)
at NHibernate.Event.Default.AbstractVisitor.Process(Object obj, IEntityPersister persister)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformUpdate(SaveOrUpdateEvent event, Object entity, IEntityPersister persister)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsDetached(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
at ET.Deap.DataAccessLayer.NHibernateEventListeners.CustomSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent evt) in C:\data\Projects\ET3_DEAP_TEST\ET.Deap\Data Layer\ET.Deap.DataAccessLayer\NHibernateEventListeners\CustomSaveEventListener.cs:line 46
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj)
at ET.Deap.DataAccessLayer.Repositories.Repository`2.Save(TEntity ent, Int16 projectId, ValidationResult& vr) in C:\data\Projects\ET3_DEAP_TEST\ET.Deap\Data Layer\ET.Deap.DataAccessLayer\Repositories\Repository.cs:line 178
Name and version of the database you are using:SQL Server 2005
The generated SQL (show_sql=true):Debug level Hibernate log excerpt:Read this:
http://hibernate.org/42.htmlCode:
Code: