Reputation: 17263
The following code works on insert but on update modifier
is never set, any ideas why?
The code for pre-update is being run and correctly sets the state and entity values to the desired value. However when viewing the generated sql nhibernate does not include the field in the update query.
/// <summary> Updates auditable objects </summary>
public class AuditEventListener : IPreInsertEventListener, IPreUpdateEventListener
{
private ISecurityManager securityManager;
public bool OnPreInsert( PreInsertEvent args )
{
var auditable = args.Entity as IAuditable;
if (auditable != null) {
Set( x => auditable.Creator, args.Persister, auditable, args.State, SecurityManager.Identity );
Set( x => auditable.DateAdded, args.Persister, auditable, args.State, Clock.Now );
}
return false;
}
public bool OnPreUpdate( PreUpdateEvent args )
{
var auditable = args.Entity as IAuditable;
if (auditable != null) {
Set( x => auditable.Modifier, args.Persister, auditable, args.State, SecurityManager.Identity );
//Set( x => auditable.DateModified, args.Persister, auditable, args.State, Clock.Now );
}
return false;
}
/// <summary> Type safe method to update sate and entity </summary>
private void Set<T, U>( Expression<Func<U, T>> expression, IEntityPersister persister, U instance, object[] state, T value )
{
var member = expression.Body as MemberExpression;
if (member != null) {
var index = Array.IndexOf( persister.PropertyNames, member.Member.Name );
if (index == -1) {
return;
}
state[index] = value;
var property = (member.Member as PropertyInfo);
if (property != null) {
property.SetValue( instance, value, null );
}
}
}
ISecurityManager SecurityManager
{
get { /* From IoC */ }
}
}
Upvotes: 5
Views: 1896
Reputation: 465
For us it was because NHibernate was joining tables together with the same column names; so we'd update the first instance of that column name, but not the subsequent ones. We did this:
protected void Set(IEntityPersister persister, object[] state, string propertyName, object value)
{
var index = Array.IndexOf(persister.PropertyNames, propertyName);
while (index > -1)
{
state[index] = value;
index = Array.IndexOf(persister.PropertyNames, propertyName, index + 1);
}
}
Upvotes: 0
Reputation: 17263
Edit 1: This answer has been improved
Edit 2: It appears the the real cuase of the problem is dynamic-update set to true as found here however this solution still works for me.
The changes get saved when you update them in the OnFlushDirty function which is called earlier.
public override bool OnFlushDirty( object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types )
{
bool result = false;
if (entity is IAuditable) {
var auditable = (IAuditable)entity;
Set( x => auditable.Modifier, propertyNames, auditable, currentState, SecurityManager.Identity );
//Set( x => auditable.DateModified, args.Persister, auditable, args.State, TwentyClock.Now );
result = true;
}
return result;
}
Upvotes: 3