I am having a problem with deleting a newly created object within a session. From what i can see i am getting an extra update statement generated prior to deletion. It seems like session thinks that i have a dirty object.
Here is what i am trying to doin my test:
1. I create a new User object and save it
2. I retrieve 1 exisiting Role object
3. I associate user and role and persist
4. I retrieve User obeject and verify that role is associated with a user.
5. Delete newly created User object, which should delete role mapping first and then remove itself.
It works fine if I close current session and do delete from another session.
I have many to many mapping between user and role.
I am using
NHibernate 1.2.0 Beta2, Oracle 10G Release2, C#
Please help me, I am lost at this point. :(
Error Stack Trace
NHibernate.StaleObjectStateException was caught
Message="Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) for CM.Business.Entity.User instance with identifier: 682"
Source="NHibernate"
StackTrace:
at NHibernate.Persister.Entity.AbstractEntityPersister.Check(Int32 rows, Object id, Int32 tableNumber, IExpectation expectation, IDbCommand statement)
at NHibernate.Persister.Entity.AbstractEntityPersister.Delete(Object id, Object version, Int32 j, Object obj, SqlCommandInfo sql, ISessionImplementor session, Object[] loadedState)
at NHibernate.Persister.Entity.AbstractEntityPersister.Delete(Object id, Object version, Object obj, ISessionImplementor session)
at NHibernate.Impl.ScheduledDeletion.Execute()
at NHibernate.Impl.SessionImpl.Execute(IExecutable executable)
at NHibernate.Impl.SessionImpl.ExecuteAll(IList list)
at NHibernate.Impl.SessionImpl.Execute()
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at DA.Persistence.Accessor.Delete[T](IList`1 entities) in C:\VSProjects\CaseManagement\Source\Data Access Layer\CaseManagement.DataAccess\Persistence\Accessor.cs:line 159
at CM.DataAccess.Repository.Delete[T](IList`1 entities) in C:\VSProjects\CaseManagement\Source\Data Access Layer\CaseManagement.DataAccess\Repository\Repository.cs:line 192
at CM.DataAccess.Repository.Delete[T](T entity) in C:\VSProjects\CaseManagement\Source\Data Access Layer\CaseManagement.DataAccess\Repository\Repository.cs:line 163
at TestCaseManagementBusiness.TestHelper.CleanupObject(IPersistDelete obj) in C:\VSProjects\CaseManagement\Tests\TestCaseManagementBusiness\TestHelper.cs:line 27
Generated Session SQL
Quote:
saving a new User
NHibernate: select MCM.PERSON_S.nextval from dual
NHibernate: INSERT INTO MCM.PERSON (MODIFIEDVERSION, CREATEDBY, CREATEDDATE, MODIFIEDBY, MODIFIEDDATE, USERNAME, NAME_FIRST, NAME_LAST, EMPLOYEEID, PHONE_OFFICE, PHONE_FAX, EMAIL, ENABLED, SUPERVISORIS, COLLEAGUE, TITLE, ADDRESS1, ADDRESS2, CITY, STATE, ZIPCODE, COUNTY, COUNTYOTHER, COUNTRY, OFFICEID, SUPERVISORID, PERSONID) VALUES (:p0, :p1, :p2, :p3, :p4, :p5, :p6, :p7, :p8, :p9, :p10, :p11, :p12, :p13, :p14, :p15, :p16, :p17, :p18, :p19, :p20, :p21, :p22, :p23, :p24, :p25, :p26); :p0 = '1', :p1 = '', :p2 = '', :p3 = '', :p4 = '', :p5 = 'Test 633005937534062500', :p6 = 'TestFirst', :p7 = 'TestLast 633005937534062500', :p8 = 'EMPLOYEEID', :p9 = '1234567890', :p10 = '1234567890', :p11 =
'test@testland.com', :p12 = 'True', :p13 = 'True', :p14 = 'False', :p15 = 'Test Title', :p16 = 'Test Line1', :p17 = 'Test Line 2', :p18 = 'Test City', :p19 = 'OH', :p20 = '12345', :p21 = 'Other', :p22 = 'Test County Other', :p23 = 'USA', :p24 = '', :p25 = '', :p26 = '682'
--AuditInterceptor.PostFlush called for object: User, id:682
Quote:
Getting 1 Role
NHibernate: SELECT applicatio0_.SECURITY_ROLEID as SECURITY1_4_0_, applicatio0_.MODIFIEDVERSION as MODIFIED2_4_0_, applicatio0_.MODIFIEDBY as MODIFIEDBY4_0_, applicatio0_.MODIFIEDDATE as MODIFIED4_4_0_, applicatio0_.ROLENAME as ROLENAME4_0_, applicatio0_.ROLEDESC as ROLEDESC4_0_, applicatio0_.ENABLED as ENABLED4_0_ FROM MCM.SECURITY_ROLE applicatio0_ WHERE applicatio0_.SECURITY_ROLEID=:p0; :p0 = '1'
NHibernate: SELECT usersecuri0_.SECURITY_ROLEID as SECURITY1___0_, usersecuri0_.RIGHT_TITLE as RIGHT2_0_, usersecuri0_.INDEXNUM as INDEXNUM__0_ FROM MCM.SECURITY_RIGHT usersecuri0_ WHERE usersecuri0_.SECURITY_ROLEID=:p0; :p0 = '1'
--AuditInterceptor.OnLoad called for entity: ApplicationRoleRefType
Quote:
update User object with newly created role, correct version increment
--AuditInterceptor.OnFlushDirty called for entity: User
NHibernate: UPDATE MCM.PERSON SET
MODIFIEDVERSION = :p0, CREATEDBY = :p1, CREATEDDATE = :p2, MODIFIEDBY = :p3, MODIFIEDDATE = :p4, USERNAME = :p5, NAME_FIRST = :p6, NAME_LAST = :p7, EMPLOYEEID = :p8, PHONE_OFFICE = :p9, PHONE_FAX = :p10, EMAIL = :p11, ENABLED = :p12, SUPERVISORIS = :p13, COLLEAGUE = :p14, TITLE = :p15, ADDRESS1 = :p16, ADDRESS2 = :p17, CITY = :p18, STATE = :p19, ZIPCODE = :p20, COUNTY = :p21, COUNTYOTHER = :p22, COUNTRY = :p23, OFFICEID = :p24, SUPERVISORID = :p25 WHERE PERSONID = :p26
AND MODIFIEDVERSION = :p27; :p0 = '2', :p1 = '', :p2 = '', :p3 = 'Test_CORP\GovorinA', :p4 = '', :p5 = 'Test 633005937534062500', :p6 = 'TestFirst', :p7 = 'TestLast 633005937534062500', :p8 = 'EMPLOYEEID', :p9 = '1234567890', :p10 = '1234567890', :p11 =
'test@testland.com', :p12 = 'True', :p13 = 'True', :p14 = 'False', :p15 = 'Test Title', :p16 = 'Test Line1', :p17 = 'Test Line 2', :p18 = 'Test City', :p19 = 'OH', :p20 = '12345', :p21 = 'Other', :p22 = 'Test County Other', :p23 = 'USA', :p24 = '', :p25 = '', :p26 = '682',
p27 = '1':
NHibernate: INSERT INTO MCM.SECURITY_USER_ROLE (PERSONID, INDEXNUM, SECURITY_ROLEID) VALUES (:p0, :p1, :p2); :p0 = '682', :p1 = '0', :p2 = '1'
--AuditInterceptor.PostFlush called for object: ApplicationRoleRefType, id:1
--AuditInterceptor.PostFlush called for object: User, id:682
Quote:
Getting user object and checking to see if role is there
NHibernate: SELECT this_.PERSONID as PERSONID1_0_, this_.MODIFIEDVERSION as MODIFIED2_1_0_, this_.CREATEDBY as CREATEDBY1_0_, this_.CREATEDDATE as CREATEDD4_1_0_, this_.MODIFIEDBY as MODIFIEDBY1_0_, this_.MODIFIEDDATE as MODIFIED6_1_0_, this_.USERNAME as USERNAME1_0_, this_.NAME_FIRST as NAME8_1_0_, this_.NAME_LAST as NAME9_1_0_, this_.EMPLOYEEID as EMPLOYEEID1_0_, this_.PHONE_OFFICE as PHONE11_1_0_, this_.PHONE_FAX as PHONE12_1_0_, this_.EMAIL as EMAIL1_0_, this_.ENABLED as ENABLED1_0_, this_.SUPERVISORIS as SUPERVI15_1_0_, this_.COLLEAGUE as COLLEAGUE1_0_, this_.TITLE as TITLE1_0_, this_.ADDRESS1 as ADDRESS18_1_0_, this_.ADDRESS2 as ADDRESS19_1_0_, this_.CITY as CITY1_0_, this_.STATE as STATE1_0_, this_.ZIPCODE as ZIPCODE1_0_, this_.COUNTY as COUNTY1_0_, this_.COUNTYOTHER as COUNTYO24_1_0_, this_.COUNTRY as COUNTRY1_0_, this_.OFFICEID as OFFICEID1_0_, this_.SUPERVISORID as SUPERVI27_1_0_ FROM MCM.PERSON this_ WHERE this_.USERNAME = :p0; :p0 = 'Test 633005937534062500'
--AuditInterceptor.PostFlush called for object: ApplicationRoleRefType, id:1
--AuditInterceptor.PostFlush called for object: User, id:682
Quote:
deleting user object, on the delete prior to delete sql i have an update generated, at this point user object is not dirty, even if it is dirty, version number on the update makes no sense 2 and 2? shouldn't it be 3 and 2. I am lost at this point
--AuditInterceptor.OnFlushDirty called for entity: User
NHibernate: UPDATE MCM.PERSON SET
MODIFIEDVERSION = :p0, CREATEDBY = :p1, CREATEDDATE = :p2, MODIFIEDBY = :p3, MODIFIEDDATE = :p4, USERNAME = :p5, NAME_FIRST = :p6, NAME_LAST = :p7, EMPLOYEEID = :p8, PHONE_OFFICE = :p9, PHONE_FAX = :p10, EMAIL = :p11, ENABLED = :p12, SUPERVISORIS = :p13, COLLEAGUE = :p14, TITLE = :p15, ADDRESS1 = :p16, ADDRESS2 = :p17, CITY = :p18, STATE = :p19, ZIPCODE = :p20, COUNTY = :p21, COUNTYOTHER = :p22, COUNTRY = :p23, OFFICEID = :p24, SUPERVISORID = :p25 WHERE PERSONID = :p26
AND MODIFIEDVERSION = :p27; p0 = '2',: :p1 = '', :p2 = '', :p3 = 'Test_CORP\GovorinA', :p4 = '', :p5 = 'Test 633005937534062500', :p6 = 'TestFirst', :p7 = 'TestLast 633005937534062500', :p8 = 'EMPLOYEEID', :p9 = '1234567890', :p10 = '1234567890', :p11 =
'test@testland.com', :p12 = 'True', :p13 = 'True', :p14 = 'False', :p15 = 'Test Title', :p16 = 'Test Line1', :p17 = 'Test Line 2', :p18 = 'Test City', :p19 = 'OH', :p20 = '12345', :p21 = 'Other', :p22 = 'Test County Other', :p23 = 'USA', :p24 = '', :p25 = '', :p26 = '682',
p27 = '2':
NHibernate: DELETE FROM MCM.SECURITY_USER_ROLE WHERE PERSONID = :p0; :p0 = '682'
NHibernate: DELETE FROM MCM.PERSON WHERE PERSONID = :p0 AND MODIFIEDVERSION = :p1; :p0 = '682', :p1 = '2'
My Mapping Structure
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="CM.Business.Entity.User, CaseManagement.Business" table="MCM.PERSON">
<id column="PERSONID" type="Int32" name="Id" access="field.camelcase-underscore" unsaved-value="0">
<generator class="NHibernate.Id.SequenceGenerator">
<param name="sequence">MCM.PERSON_S</param>
</generator>
</id>
<version
column="MODIFIEDVERSION"
name="Version"
type="Int32"
access="field.camelcase-underscore"
/>
<property column="CREATEDBY" type="String" name="CreatedBy" access="field.camelcase-underscore"/>
<property column="CREATEDDATE" type="DateTime" name="CreatedDate" access="field.camelcase-underscore"/>
<property column="MODIFIEDBY" type="String" name="LastUpdatedBy" access="field.camelcase-underscore"/>
<property column="MODIFIEDDATE" type="DateTime" name="LastUpdatedDate" access="field.camelcase-underscore"/>
<property column="USERNAME" type="String" name="Username" access="field.camelcase-underscore"/>
<property column="NAME_FIRST" type="String" name="FirstName" access="field.camelcase-underscore"/>
<property column="NAME_LAST" type="String" name="LastName" access="field.camelcase-underscore"/>
<property column="EMPLOYEEID" type="String" name="ExternalId" access="field.camelcase-underscore"/>
<property column="PHONE_OFFICE" type="String" name="Phone" access="field.camelcase-underscore"/>
<property column="PHONE_FAX" type="String" name="Fax" access="field.camelcase-underscore"/>
<property column="EMAIL" type="String" name="Email" access="field.camelcase-underscore"/>
<property column="ENABLED" type="Boolean" name="Enabled" access="field.camelcase-underscore"/>
<property column="SUPERVISORIS" type="Boolean" name="IsSupervisor" access="field.camelcase-underscore"/>
<property column="COLLEAGUE" type="Boolean" name="IsCollegue" access="field.camelcase-underscore"/>
<property column="TITLE" type="String" name="Title" access="field.camelcase-underscore"/>
<component class ="CM.Business.Entity.User+UserAddress, CaseManagement.Business" name="Address">
<property column="ADDRESS1" type="String" name="AddressLine1" access="field.camelcase-underscore"/>
<property column="ADDRESS2" type="String" name="AddressLine2" access="field.camelcase-underscore"/>
<property column="CITY" type="String" name="City" access="field.camelcase-underscore"/>
<property column="STATE" type="String" name="State" access="field.camelcase-underscore"/>
<property column="ZIPCODE" type="String" name="ZipCode" access="field.camelcase-underscore"/>
<property column="COUNTY" type="String" name="County" access="field.camelcase-underscore"/>
<property column="COUNTYOTHER" type="String" name="CountyOther" access="field.camelcase-underscore"/>
<property column="COUNTRY" type="Int32" name="Country" access="field.camelcase-underscore"/>
</component>
<many-to-one column="OFFICEID" name="Office" class="CM.Business.Entity.Office, CaseManagement.Business" access="field.camelcase-underscore"/>
<many-to-one column="SUPERVISORID" name="Supervisor" class="CM.Business.Entity.User, CaseManagement.Business" access="field.camelcase-underscore"/>
<list name="SecurityRoles" table="MCM.SECURITY_USER_ROLE" lazy="true">
<key column="PERSONID" />
<index column="INDEXNUM" type="Int32" />
<many-to-many column="SECURITY_ROLEID" class="CM.Reference.ApplicationRoleRefType, CaseManagement.Business" />
</list>
</class>
<class name="CM.Reference.ApplicationRoleRefType, CaseManagement.Business" table="MCM.SECURITY_ROLE">
<id column="SECURITY_ROLEID" type="Int32" name="Id" access="field.camelcase-underscore" unsaved-value="0">
<generator class="NHibernate.Id.SequenceGenerator">
<param name="sequence">MCM.SECURITY_ROLE_S</param>
</generator>
</id>
<version
column="MODIFIEDVERSION"
name="Version"
type="Int32"
access="field.camelcase-underscore"
/>
<property column="MODIFIEDBY" type="String" name="LastUpdatedBy" access="field.camelcase-underscore"/>
<property column="MODIFIEDDATE" type="DateTime" name="LastUpdatedDate" access="field.camelcase-underscore"/>
<property column="ROLENAME" type="String" name="Value" access="field.camelcase-underscore"/>
<property column="ROLEDESC" type="String" name="Description" access="field.camelcase-underscore"/>
<property column="ENABLED" type="Boolean" name="Enabled" access="field.camelcase-underscore"/>
<array table="MCM.SECURITY_RIGHT" name="UserSecurityRights" access ="field.camelcase-underscore">
<key column="SECURITY_ROLEID" foreign-key="SECURUTY_ROLEID"></key>
<index column="INDEXNUM" type="Int32"></index>
<element column="RIGHT_TITLE" type ="String"></element>
</array>
</class>
</hibernate-mapping>
My Test method, UserLogic class is just a helper class that deals with NHibernate and Session managementCode:
CM.BusinessLogic.UserLogic uc = new CM.BusinessLogic.UserLogic();
User currentUser = NewUser();
uc.SaveUser(currentUser);
CM.BusinessLogic.ApplicationRoleRefTypeLogic arLogic = new CM.BusinessLogic.ApplicationRoleRefTypeLogic();
IList<ApplicationRoleRefType> roles = new List<ApplicationRoleRefType>();
roles.Add(arLogic.GetRole(1));
currentUser.SecurityRoles = roles;
//Console.WriteLine("before save id{0}, ver{1}", _user.Id.ToString(), _user.Version.ToString());
uc.SaveUser(currentUser);
//Console.WriteLine("after save id{0}, ver{1}", _user.Id.ToString(), _user.Version.ToString());
User u = uc.GetUser(currentUser.Id);
Assert.AreEqual(roles.Count, u.SecurityRoles.Count, "CM.BusinessLogic.UserLogic.SaveUser has failed to save user and security roles.");
uc.DeleteUser(currentUser);