2011-06-30 1 views
3

J'ai une entité avec de nombreuses relations un-à-un (cascade = "all-delete-orphelin") et des collections.Vérifier si l'entité (propriétés et collections) est sale

Je veux vérifier est cette entité est sale (y compris ses collections et propriétés/entités de ces relations un-à-un), est-il possible de le faire?

J'ai suivi this article mais il ne couvre pas tout ce dont j'ai besoin, toute aide sera appréciée.

+0

BTW: Je veux faire ceci, pour valider si l'utilisateur peut quitter le formulaire ou si je devrais le prévenir des changements non enregistrés – dimirc

Répondre

0

Vous pouvez utiliser un auditeur NHibernate, comme ceci:

public class AuditUpdateListener : IPostUpdateEventListener 
{ 
    private const string _noValueString = "*No Value*"; 

    private static string getStringValueFromStateArray(object[] stateArray, int position) 
    { 
     var value = stateArray[position]; 

     return value == null || value.ToString() == string.Empty 
       ? _noValueString 
       : value.ToString(); 
    } 

    public void OnPostUpdate(PostUpdateEvent @event) 
    { 
     if (@event.Entity is AuditLogEntry) 
     { 
      return; 
     } 

     var entityFullName = @event.Entity.GetType().FullName; 

     if (@event.OldState == null) 
     { 
      throw new ArgumentNullException("No old state available for entity type '" + entityFullName + 
              "'. Make sure you're loading it into Session before modifying and saving it."); 
     } 

     int[] dirtyFieldIndexes = @event.Persister.FindDirty(@event.State, @event.OldState, @event.Entity, @event.Session); 

     ISession session = @event.Session.GetSession(EntityMode.Poco); 

     string entityName = @event.Entity.GetType().Name; 
     string entityId = @event.Id.ToString(); 

     foreach (int dirtyFieldIndex in dirtyFieldIndexes) 
     { 
      //For component types, check: 
      // @event.Persister.PropertyTypes[dirtyFieldIndex] is ComponentType 

      var oldValue = getStringValueFromStateArray(@event.OldState, dirtyFieldIndex); 
      var newValue = getStringValueFromStateArray(@event.State, dirtyFieldIndex); 

      if (oldValue == newValue) 
      { 
       continue; 
      } 

      // Log 
      session.Save(new AuditLogEntry 
           { 
            EntityShortName = entityName, 
            FieldName = @event.Persister.PropertyNames[dirtyFieldIndex], 
            EntityFullName = entityFullName, 
            OldValue = oldValue, 
            NewValue = newValue, 
            Username = Environment.UserName, 
            EntityId = entityId, 
            AuditEntryType = AuditEntryType.PostUpdate 
           }); 
     } 

     session.Flush(); 
    } 
} 
+0

Mais ce serait pendant le rinçage et ce n'est pas ce que je veux. Aussi, je ne pense pas que cela ira à travers les collections. – dimirc

+0

Qu'en est-il de PreUpdateEventListener? Ce sont les meilleures méthodes ... – rebelliard

1

La méthode onFlushDirty(...) (étend EmptyInterceptor en veille prolongée) fonctionne pour moi de vérifier collection sale. L'entité parent avec la collection imbriquée est passée dans onFlushDirty, mais je ne savais pas que l'entité transmise pouvait être l'élément de collection. Une fois que j'ai trouvé cela, cela a fonctionné à la fois pour la collection imbriquée et pour son entité parente.

public class PropertyChangeInterceptor extends EmptyInterceptor{ 

public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) 

Une autre méthode, onCollectionUpdate(...) peut également être utilisé pour attraper la collection sale, il est appelé après onFlushDirty(...).

Questions connexes