NHibernate Forge
The official new home for the NHibernate for .NET community

Finding Dirty Properties in NHibernate

Wiki Page Hierarchy

Pages

Page Details

First published by:
Ricardo Peres
on 10-09-2009
Last revision by:
Ricardo Peres
on 06-20-2011
1 person found this article useful.
Article
Comments (9)
History (7)
50% of people found this useful

Finding Dirty Properties in NHibernate

UPDATE: now deals properly with proxies.

The following extension methods to ISession allow finding if a property or entity has changed, and the original value of a property.

 

public static class SessionExtensions

{

    public static Boolean IsDirtyEntity(this ISession session, Object entity)

    {

        ISessionImplementor sessionImpl = session.GetSessionImplementation();

        IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;

        EntityEntry oldEntry = persistenceContext.GetEntry(entity);

        String className = oldEntry.EntityName;

        IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);

 

        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 = oldState.Select((o, i) => (oldState [ i ] == currentState [ i ]) ? -1 : i).Where(x => x >= 0).ToArray();

 

        return (dirtyProps != null);

    }

 

    public static Boolean IsDirtyProperty(this ISession session, Object entity, String propertyName)

    {

        ISessionImplementor sessionImpl = session.GetSessionImplementation();

        IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;

        EntityEntry oldEntry = persistenceContext.GetEntry(entity);

        String className = oldEntry.EntityName;

        IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);

 

        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)

    {

        ISessionImplementor sessionImpl = session.GetSessionImplementation();

        IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;

        EntityEntry oldEntry = persistenceContext.GetEntry(entity);

        String className = oldEntry.EntityName;

        IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);


        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 ]);

    }

}

 

Recent Comments

By: Todd Aspeotis Posted on 11-29-2013 0:17
100% of people found this useful

I went to use this code to find dirty properties but after reading the first function I have no idea what it's meant to do.

* oldEntry is checked against null AFTER it's been used (oldEntry.EntityName)

* oldState[i] == currentState[i] won't necessarily work when you have boxed value types

* The function will always return true (ToArray never returns null; at a minimum you'll have an empty array

By: Ricardo Peres Posted on 06-07-2011 10:31

@Jaguar:

Yes, that is by design: a non-mutable entity will never be saved back.

By: Ricardo Peres Posted on 06-07-2011 10:30

@a_rasekh:

If it comes from a different session, there's no way to know if it is dirty. The only way is to update the database with the current state of the object (Merge) or update the object with the current state of the database (Refresh).

By: Jaguar Posted on 04-05-2011 6:08

Actually is you set mutable="false" on an entity the LoadedState property will always be null which is a bummer

By: Eduard Stanculet Posted on 02-18-2011 5:03

I have the same problem with OldEntity is null

I think i am in a different session

View All
Powered by Community Server (Commercial Edition), by Telligent Systems