Not an Issue
Details
Details
Assignee
Unassigned
UnassignedReporter
Simon Taylor
Simon TaylorComponents
Affects versions
Priority
Who's Looking?
Open Who's Looking?
Created October 2, 2007 at 3:19 AM
Updated May 17, 2009 at 2:02 PM
Resolved May 17, 2009 at 2:02 PM
This relates to a post that I have already added to the forum (http://forum.hibernate.org/viewtopic.php?p=2366058#2366058). In addition to this post (which I have copied below for convenience) I have also attached example code which clearly shows the problem. As the code stands, it shows IInterceptor firing as expected - uncommenting a single line then shows the problem I describe below.
Hi, I am attempting to make use of IInterceptor in order to implement auditing. I'm having problems because when I call ICriteria.UniqueResult<T>(), which forces a flush to occur and therefore my interceptor to fire, the internal state of the entities that have changed doesn't seem to get updated. This means that if/when flush gets called again, my interceptor fires again and I get duplicate entries in my audit log - any thoughts???? It seems like a bug to me.
I presume that that changing the flush mode to "commit" is one way that this problem could be resolved, however, auditing has been bolted on at the end of a sizable project, so I would be reluctant to start changing the flush mode now, since I would be fearful of what else it might break.
Hibernate version: 1.2.0.GA
Name and version of the database you are using: SQLServer 2000
Please find a more detailed explanation of the scenario below:
In the OnFlushDirty method of the interceptor I loop through all of the names in the propertyNames array, I then compare corresponding values in the currentState array and the previousState array and write an entry to the log if there is a difference.
Now consider the following:
ISession session = NHibernateSessionManager.Instance.GetSession();
Contact contact = session.Get<Contact>(1); // Read contact "Dave"
contact.PreferredName = "Updated preferred name";
session.Flush(); // #### Flush 1 ####
contact.Forename = "Updated forename";
session.Flush(); // #### Flush 2 ####
session.SaveOrUpdateCopy(contact);
In this scenario everything happens as I would expect. When "flush 1" occurs the entries in previousState array and currentState array for the PreferredName field of contact have "Dave" and "Updated preferred name" respectively. There is a difference and therefore an entry is written to the audit log. When "flush 2" occurs the entries in previousState array and currentState array for the Forename field are different, and the entries for PreferredName both have the new value of "Updated preferred name"; this results in one extra audit log entry for the change to the Forename field.
In the scenario I am having a problem with, before "Flush 2" happens I am reading another record using an ICriteria object to build up a query and return the result of ICriteria.UniqueResult<T>(). When UniqueResult() fires it forces a flush which again results in a single audit record being written, however, when "Flush 2" occurs, the internal state doesn't seem to have been updated when UniqueResult() was called. This means that my interceptor fires again, and when the currentState and previousState of the Forename field are compared they are different rather than both having the value "Updated Forename" I therefore end up with two entries in my audit log for the change to the forename field.
**********************************************
In addition to this, when creating the example code I discovered that if you create an ICriteria object to query the same table (in the example above Contact), the problem doesn't show itself, it only occurs if you query something different.