2010-07-20 9 views
0

Je veux avoir quelque chose comme des sous-transactions, en ce que vous pouvez marquer un point où vous commencerez la sous-transaction, puis au point de descection pour ce bit, vous pouvez annuler (annuler le sous-bit) ou continuer, en s'engageant efficacement, lorsque la trans mission sort. Bien sûr, si vous annulez la transaction externe, le bit marqué est également abandonné.Comment gérer des sous-transactions ou des transactions imbriquées?

Comment puis-je faire avec NHibernate, mais la transaction est fermée pendant la fisrt commettras et i`m ayant ainsi le message d'erreur

aucune transaction ouverte à commettre

Mon code est comme suit:

API.Data.Session session = API.Data.SessionManager.GetSession(); 
     session.BeginTransaction(); 
     try 
     { 
      Project project = Project.Load(ID); 
      ........... 
      Save(project); 
      ..................... 

      session.CommitTransaction(); 
     } 
     catch 
     { 
      session.RollbackTransaction(); 
      throw; 
     } 

public void save(Project project) 
    { 
Data.SessionManager.GetSession().BeginTransaction(); 
       try 
       { 
        Save(); 
        LogIssueChange(test); 
        Data.SessionManager.GetSession().CommitTransaction(); 
       } 
       catch 
       { 
        Data.SessionManager.GetSession().RollbackTransaction(); 
        throw; 
       } 
    } 

Répondre

1

Le support natif est fourni par les transactions et la emboîtées classe TransactionScope. Sachez que AFAIK est supporté par Sql Server et Oracle bien qu'il puisse fonctionner pour d'autres bases de données si elles supportent des transactions distribuées ainsi que l'API qui se connecte à System.Data le supporte également.

voir ces questions SO https://stackoverflow.com/questions/tagged/nhibernate+transactionscope

1

Vous ne pouvez pas, NHibernate ne prend pas en charge les transactions imbriquées. Vous pourriez être en mesure d'atteindre cet objectif avec l'espace de noms Systems.Transaction.


Édition: L'implémentation de DeferableTransaction est ci-dessous. J'ai ceci comme une méthode d'extension sur ISession. Cela dit, l'utilisation a été très rare.

Méthodes d'extension:

public static DeferableTransaction BeginOrDeferTransaction(this ISession session) 
    { 
     return new DeferableTransaction(session); 
    } 

    public static DeferableTransaction BeginOrDeferTransaction(this ISession session, IsolationLevel isolationLevel) 
    { 
     return new DeferableTransaction(session, isolationLevel); 
    } 

Mise en œuvre:

/// <summary> 
/// Begins a transaction or defers to an existing transaction. The IsolationLevel will not be changed 
/// on an existing transaction. 
/// </summary> 
public class DeferableTransaction : IDisposable 
{ 
    private readonly bool _ownedTransaction; 
    private readonly ITransaction _transaction; 

    public DeferableTransaction(ISession session) 
     : this(session, IsolationLevel.ReadCommitted) 
    {} 

    public DeferableTransaction(ISession session, IsolationLevel isolationLevel) 
    { 
     if (session.Transaction.IsActive) 
     { 
      _ownedTransaction = false; 
      _transaction = session.Transaction; 
     } 
     else 
     { 
      _ownedTransaction = true; 
      _transaction = session.BeginTransaction(isolationLevel); 
     } 
    } 

    public bool OwnedTransaction 
    { 
     get { return _ownedTransaction; } 
    } 

    public void CommitOrDefer() 
    { 
     if (_ownedTransaction) 
     { 
      _transaction.Commit(); 
     } 
    } 

    public void RollbackOrDefer() 
    { 
     if (_ownedTransaction) 
     { 
      _transaction.Rollback(); 
     } 
    } 

    public void Enlist(IDbCommand command) 
    { 
     _transaction.Enlist(command); 
    } 

    public bool IsActive 
    { 
     get { return _transaction.IsActive; } 
    } 

    public bool WasCommitted 
    { 
     get { return _transaction.WasCommitted; } 
    } 

    public bool WasRolledBack 
    { 
     get { return _transaction.WasRolledBack; } 
    } 

    public void Dispose() 
    { 
     if (_ownedTransaction) 
     { 
      _transaction.Dispose(); 
     } 
    } 
} 
+0

N'y a-t-il pas d'autre méthode? Je ne veux pas interagir directement avec la base de données – learning

+0

Non, il n'y a pas d'autre moyen. Je ne mets pas du tout les transactions dans les méthodes de référentiel/service avec NHibernate afin que plusieurs méthodes de référentiel puissent participer à la même transaction. Il y a très rarement un besoin de transactions imbriquées en dehors des systèmes distribués. J'ai une méthode d'extension pour ISession appelée DeferableTransaction qui utilise une sémantique similaire et permet à une transaction de reporter à une transaction existante ou de commencer une nouvelle transaction. Je l'afficherai si vous êtes intéressé. –

+0

ne peut pas parler pour le PO, mais je serais intéressé à voir votre impl – DanP

Questions connexes