Search code examples
c#nhibernatefluent-nhibernateinterceptor

NHibernate Interceptor - OnFlushDirty


What I want to do is to intercept entity on save and truncate some string properties.

The issues is that OnSave() triggers only for new Entity, but not on changing/updating Entity.

Then there is OnFlushDirty() interceptor. But I am really confused with this one.

So I want to modify some property of entity on updating entity, like:

public bool OnFlushDirty( 
             object entity, 
             object id, 
             object[] currentState, 
             object[] previousState,  
             string[] propertyNames, 
             IType[] types)
{
      bool entityChanged = false;
      for (int i = 0; i < propertyNames.Length; i++)
      {
            var stringType = types[i] as NHibernate.Type.StringType;

            if (stringType != null)
            {
                 if(NeedTruncate(currentState[i]))
                 {
                      currentState[i] = Truncate(currentState[i]);
                      entityChanged = true;
                 }
            }
      }

      return entityChanged;
}

So the issue is next. On some blogs like this one I read that OnFlushDirty() is called when entity was changed and saved into database, so the changes to any property here will not be saved into database.

But in githab.io documentation it says:

The interceptor may modify the detected currentState, which will be propagated to both the database and the persistent object. Note that all flushes end in an actual synchronization with the database, in which as the new currentState will be propagated to the object, but not necessarily (immediately) to the database. It is strongly recommended that the interceptor not modify the previousState.

It also says:

Called when an object is detected to be dirty, during a flush.

So I am not sure what exactly means

Called when an object is detected to be dirty

Also regarding to this documentation, the changes will be saved into database, just not necessary immediately.

Anyway, by testing this in my project, this works and when OnFlushDirty() is called and it changes value of some property it's also saved in database and all seams to be working fine.

So my question is: Is this correct to do? As I said, I tested it with my project and on changing/updating entity OnFlushDirty() is called, property is changed and saved into database as well. Just because all of this, and weak documentation, I am not sure if I can run into some issues with this?


Solution

  • What I do, in a similar case, is override the FindDirty method of the interceptor, and return an array of indexes for the properties that have changes (or that you will change in the flushdirty).

    In your case, you could override that method and check in that method whether or not you have some string properties that should be truncated. If so, return the indexes of those properties.

    By doing so, you should be sure that OnFlushDirty is always called when it is necessary for you.

    Next to that, OnFlushDirty should also return true if you have modified a persistent property in that method, which you do not do as far as I can see in your code that is posted here.