views:

32

answers:

2

I have a problem getting my change(s) to data object retrieved using NHibernate to persist back into the database. I get no exceptions so it's difficult to know where to look. Any suggestions?

string name = "somenewname";
string repositoryId = "somerepositoryid";

ISession nhbSession = GetNhbSession(session);
nhbSession.Transaction.Begin();
try
{
    RepositoryDto existingRepository = nhbSession.Get<RepositoryDto>(repositoryId);
    if (existingRepository == null || existingRepository.TimeDeleted != null)
        throw new Exception("Repository does not exist in system or is deleted. Cannot modify.");

    existingRepository.Name = name; //works fine up to here as expected; is in DB with old name
    nhbSession.Update(existingRepository);
    nhbSession.Transaction.Commit();
}
catch (Exception ex)
{
    nhbSession.Transaction.Rollback();
    throw new Exception("Error modifying repository: " + ex.Message, ex);
}


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SomeComponent"
  namespace="SomeComponent.Repository.DTO" auto-import="true" default-lazy="false">
  <class name="RepositoryDto" table="Repository" mutable="false">  
    <id name="RepositoryId" column="repositoryId" unsaved-value="0">
      <generator class="assigned"/>
    </id>
    <property name="SystemId" column="systemId" not-null="true" />
    <property name="TimeCreated" column="timeCreated" not-null="true" />
    <property name="TimeDeleted" column="timeDeleted" not-null="false" />
    <property name="Name" column="name" not-null="true" />
  </class>
</hibernate-mapping>
+1  A: 

You're missing the Flush:

// etc...
nhbSession.Update(existingRepository);
nhbSession.Flush();
nhbSession.Transaction.Commit();
// etc...

More: Committing the database transaction

Rafael Belliard
Adding flush doesn't change the behaviour. I have tried. It should not be needed though, because it will autoflush on commit by default. Thanks all the same.
Lisa
@Lisa: could you try using <begintransaction> instead of tx.Begin(), like http://www.codepaste.net/nji87s ?
Rafael Belliard
Thanks again, but it appears that ensuring disposal of the transaction still doesn't help. I even tried disposing the session in case something was missing.I know that the changes are being made to the NHibernate 'local or cached' version of the RepositoryDto object because if I do another Get call within the transaction it has the new name. Still not persisted to DB though.
Lisa
+1  A: 

I have found the problem. There was a stray 'mutable="false"' in my RepositoryDto class mapping leftover from copy and paste of a different class mapping I presume. A really nasty one to find!!

<class name="RepositoryDto" table="Repository" mutable="false"> 

changes to

<class name="RepositoryDto" table="Repository" mutable="true"> <!-- or just delete mutable to use default of true -->

An exception from NHibernate of the form "RepositoryDto mapping says it is not mutable so you cannot call Update on this object" would be nice!

Lisa
Lol... so true.
Rafael Belliard