2009-11-04 7 views
1

Je souhaite que NHibernate annule l'identifiant de toutes les entités enregistrées lors d'une transaction si la transaction est abandonnée. J'utilise NHibernate 2.1.0, et il ne le fait pas par défaut. Je suis venu avec la solution suivante, qui fonctionne jusqu'à un certain point:Redresser les identifiants NHibernate

public class RevertIdentifiersEventListener : DefaultSaveEventListener 
{ 
    private class RevertIdentiferSynchronization : ISynchronization 
    { 
     private IClassMetadata _classMetadata; 
     private object _entity; 
     private object _originalIdentifier; 

     public RevertIdentiferSynchronization(IClassMetadata classMetadata, object entity) 
     { 
      _classMetadata = classMetadata; 
      _entity = entity; 
      _originalIdentifier = classMetadata.GetIdentifier(entity, NHibernate.EntityMode.Poco); 
     } 

     #region ISynchronization Members 

     public void AfterCompletion(bool success) 
     { 
      if (success == false) 
      { 
       _classMetadata.SetIdentifier(_entity, _originalIdentifier, NHibernate.EntityMode.Poco); 
      } 
     } 

     public void BeforeCompletion() 
     { 
     } 

     #endregion 
    } 


    protected override object EntityIsTransient(SaveOrUpdateEvent @event) 
    { 
     IEntityPersister entityPersister = @event.Session.GetEntityPersister(@event.EntityName, @event.Entity); 
     if (entityPersister.HasIdentifierProperty) 
     { 
      RevertIdentiferSynchronization revertIdentiferSynchronization = new RevertIdentiferSynchronization(entityPersister.ClassMetadata, @event.Entity); 
      if (@event.Session.Transaction.IsActive) 
      { 
       @event.Session.Transaction.RegisterSynchronization(revertIdentiferSynchronization); 
      } 
     } 
     return base.EntityIsTransient(@event); 
    } 

} 

Le problème est que si la sauvegarde d'une cascade d'entité la sauvegarde à une entité associée, l'identifiant de cette entité ne sera pas annulée. EntityIsTransient ci-dessus n'est pas appelé pour ces entités, il n'est appelé que pour ceux sur lesquels Save est explicitement appelé.

Des suggestions sur la façon de le faire fonctionner en cascade aussi?

Répondre

0

Je ne sais pas dans quelles circonstances vous voulez annuler une transaction, mais je suppose que vous avez besoin quelque chose comme ceci:

using(var transaction = SessionFactory.GetSession().BeginTransaction()) 
    { 
     try 
     { 
      session.Update(entity); // throws exception for some reason 
     } 
     catch(Exception ex) 
     { 
      transaction.Rollback(); // rollback the transaction 
     } 
    } 
+0

Elle demande ce que vous faites après un retour en arrière. J'ai ce même problème. Si l'entité contient une référence à un nouveau modèle enfant et NHibernate essaye d'insérer cette entité enfant, il change son identifiant (un Guid) pour qu'il ne soit plus un nouveau Guid(). Nous avons besoin de restaurer l'identifiant des objets enfants d'une manière ou d'une autre, de manière à ce que nous sachions qu'il n'a jamais été désactivé. – ctrlShiftBryan

Questions connexes