Finding Dirty Properties in NHibernate

Sometimes there may be a need for finding out if a specific entity, or a property of that entity, was changed, or, better yet, the original value for that property.

Below is a set of extensions for ISession that give you just that.

 

public static class SessionExtensions
	{
		public static Boolean IsDirtyEntity(this ISession session, Object entity)
		{
			String className = NHibernateProxyHelper.GuessClass(entity).FullName;
			ISessionImplementor sessionImpl = session.GetSessionImplementation();
			IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;
			IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);
			EntityEntry oldEntry = sessionImpl.PersistenceContext.GetEntry(entity);

			if ((oldEntry == null) && (entity is INHibernateProxy))
			{
				INHibernateProxy proxy = entity as INHibernateProxy;
				Object obj = sessionImpl.PersistenceContext.Unproxy(proxy);
				oldEntry = sessionImpl.PersistenceContext.GetEntry(obj);
			}

			Object [] oldState = oldEntry.LoadedState;
			Object [] currentState = persister.GetPropertyValues(entity, sessionImpl.EntityMode);
			Int32 [] dirtyProps = persister.FindDirty(currentState, oldState, entity, sessionImpl);
			
			return (dirtyProps != null);
		}

		public static Boolean IsDirtyProperty(this ISession session, Object entity, String propertyName)
		{
			String className = NHibernateProxyHelper.GuessClass(entity).FullName;
			ISessionImplementor sessionImpl = session.GetSessionImplementation();
			IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;
			IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);
			EntityEntry oldEntry = sessionImpl.PersistenceContext.GetEntry(entity);

			if ((oldEntry == null) && (entity is INHibernateProxy))
			{
				INHibernateProxy proxy = entity as INHibernateProxy;
				Object obj = sessionImpl.PersistenceContext.Unproxy(proxy);
				oldEntry = sessionImpl.PersistenceContext.GetEntry(obj);
			}

			Object [] oldState = oldEntry.LoadedState;
			Object [] currentState = persister.GetPropertyValues(entity, sessionImpl.EntityMode);
			Int32 [] dirtyProps = persister.FindDirty(currentState, oldState, entity, sessionImpl);
			Int32 index = Array.IndexOf(persister.PropertyNames, propertyName);

			Boolean isDirty = (dirtyProps != null) ? (Array.IndexOf(dirtyProps, index) != -1) : false;

			return (isDirty);
		}

		public static Object GetOriginalEntityProperty(this ISession session, Object entity, String propertyName)
		{
			String className = NHibernateProxyHelper.GuessClass(entity).FullName;
			ISessionImplementor sessionImpl = session.GetSessionImplementation();
			IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;
			IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);
			EntityEntry oldEntry = sessionImpl.PersistenceContext.GetEntry(entity);

			if ((oldEntry == null) && (entity is INHibernateProxy))
			{
				INHibernateProxy proxy = entity as INHibernateProxy;
				Object obj = sessionImpl.PersistenceContext.Unproxy(proxy);
				oldEntry = sessionImpl.PersistenceContext.GetEntry(obj);
			}

			Object [] oldState = oldEntry.LoadedState;
			Object [] currentState = persister.GetPropertyValues(entity, sessionImpl.EntityMode);
			Int32 [] dirtyProps = persister.FindDirty(currentState, oldState, entity, sessionImpl);
			Int32 index = Array.IndexOf(persister.PropertyNames, propertyName);

			Boolean isDirty = (dirtyProps != null) ? (Array.IndexOf(dirtyProps, index) != -1) : false;

			return ((isDirty == true) ? oldState [ index ] : currentState [ index ]);
		}
	}

Bookmark and Share

                             

1 Comment

  • Ah I figured it out - me being stupid really - if the call to GetEntry will return null if the entity is new (unsaved). In this case the method should probably just return true or fail gracefully.

Comments have been disabled for this content.