Hi, I was needing calls to session.IsDirty() to not flush as it was
causing me some issues.  Also it breaks the command query seperation,
you wouldn't expect checking for dirty to change the state of the
session.

Anyway, after wandering through the NH source code and also this
http://weblogs.asp.net/ricardoperes/archive/2009/10/09/finding-dirty-properties-in-nhibernate.aspx

I came up with a NonFlushingDirtyCheckEventListener.  It seems to work
good so far, but I wanted to see if you guys might be able to do a
quick sanity check to see if this is reasonable.  (I'm still very new
to NHibernate).

Thanks,
Brian

using System;
using System.Collections;
using log4net;
using NHibernate.Util;
using NHibernate.Engine;
using NHibernate.Collection;
using NHibernate.Action;
using NHibernate.Proxy;
using NHibernate.Persister.Entity;
using NHibernate.Event;


[Serializable]
public class NonFlushingDirtyCheckEventListener :
IDirtyCheckEventListener
{
        public virtual void OnDirtyCheck(DirtyCheckEvent @event)
        {
                ICollection list =
IdentityMap.Entries(@event.Session.PersistenceContext.EntityEntries);
                foreach (DictionaryEntry me in list) {
                        if (IsEntityDirty(@event.Session, 
(EntityEntry)me.Value, me.Key)) {
                                @event.Dirty = true;
                                return;
                        }
                }

                list =
IdentityMap.Entries(@event.Session.PersistenceContext.CollectionEntries);
                foreach (DictionaryEntry item in list) {
                        if (IsCollectionDirty((CollectionEntry)item.Value,
(IPersistentCollection)item.Key)) {
                                @event.Dirty = true;
                                return;
                        }
                }

                @event.Dirty = false;
        }

        private bool IsEntityDirty(ISessionImplementor sessionImpl,
EntityEntry entityEntry, Object entity) {
                if ((entityEntry == null) && (entity is INHibernateProxy)) {
                        INHibernateProxy proxy = entity as INHibernateProxy;
                        object obj = 
sessionImpl.PersistenceContext.Unproxy(proxy);
                        entityEntry = 
sessionImpl.PersistenceContext.GetEntry(obj);
                }

                object[] oldState = entityEntry.LoadedState;
                object[] currentState =
entityEntry.Persister.GetPropertyValues(entity,
sessionImpl.EntityMode);
                int[] dirtyProps = entityEntry.Persister.FindDirty(currentState,
oldState, entity, sessionImpl);

                return (dirtyProps != null);
        }

        private bool IsCollectionDirty(CollectionEntry collectionEntry,
IPersistentCollection collection) {
                if (collection.IsDirty) return true;

                bool isDirty = (
                        collection.WasInitialized
                        && collectionEntry.LoadedPersister != null
                        && collectionEntry.LoadedPersister.IsMutable
                        && (collection.IsDirectlyAccessible ||
collectionEntry.LoadedPersister.ElementType.IsMutable)
                        && 
!collection.EqualsSnapshot(collectionEntry.LoadedPersister)
                );

                return isDirty;
        }
}

Reply via email to