tags:

views:

40

answers:

0

We have implemented an auditing system via NHibernate event listeners. In our listener, we track all changes and write them out to our audit tables. To try and maximize performance, we have used Guid's for our audit tables so that we can batch our updates as much as possible.

We are writing out updates to a "child session" which we get like this:

 protected ISession GetSession(AbstractEvent @event)
 {
     if (@event == null)
     {
        throw new ArgumentNullException("event");
     }

        ISession childSession = @event.Session.GetSession(EntityMode.Poco);

        return childSession;
 } 

From the NHibernate documentation, this session should be a "child" session, that inherits all the attributes of it's parent - including the transaction.

Once we have created the entity, we save it to the session with:

childSession.Save(auditLogEntry);

All of this is called within a transaction and I would expect that the changes made to the childSession would flush once the transaction is committed. Unfortunately, nothing is happening and the changes are not flushing.

It should be noted that I can get this to work with a manual flush right after the save, but this won't work for us because the changes will no longer be batched (which will yield unacceptable performance).

At first I thought this behavior was limited to events, but I was able to abstract it out into a unit test to duplicate the behavior.

  public void When_Saving_Audit_Log_Records_To_Child_Session_Flushes_When_Transaction_Committed()
    {
        ISession session = GetSession();
        session.FlushMode = FlushMode.Commit;

        ITransaction transaction = session.BeginTransaction();

        ISession childSession = session.GetSession(EntityMode.Poco);

        AuditLogEntry entry = CreateAuditLogEntry();
        entry.AddAuditLogEntryDetail(CreateAuditLogEntryDetail());
        entry.AddAuditLogEntryDetail(CreateAuditLogEntryDetail());

        childSession.Save(entry);
        transaction.Commit();
    }

protected ISession GetSession()
    {
        return _sessionFactory.OpenSession();
    }

I know that this is not your run of the mill NHibernate question, but if anyone has any experience or advice to share, I would love to hear it.

I am 2 seconds away from just writing the audit records out to a queue but I wanted to exhaust every possibility before giving up.

Thanks in advance,

Steve