2012-08-16 2 views
0

J'ai écrit une classe en C# destinée à offrir la possibilité d'exécuter des transactions de base de données sur une connexion de base de données donnée. Quand j'essaye d'exécuter le code cependant j'obtiens les deux erreurs suivantes sur Oracle et SQL Server respectivement. En regardant mon code, y a-t-il un moyen facile de contourner cela?C# Transactions sur Oracle et SQL Server via ADO.NET échouant

Oracle

La connexion est déjà partie d'un local ou d'une transaction distribuée

SQL Server 2008

SqlConnection ne prend pas en charge t parallèle ransactions

La classe de base

public abstract class DbFactoryDatabaseTransaction 
    { 
    public void DoTransaction(IDatabaseConnectivityObjectBasicResponse databaseConnectivityObject) 
    { 
     databaseConnectivityObject.PrepareConnection(); 

     DbTransaction dbTransaction = databaseConnectivityObject.DBFactoryDatabaseConnection.BeginTransaction(); 

     try 
     { 
      ExecuteSql(databaseConnectivityObject, dbTransaction); 

      dbTransaction.Commit(); 
     } 
     catch (Exception ex) 
     { 
      dbTransaction.Rollback(); 

      databaseConnectivityObject.Close(); 

      throw; 
     } 
     finally 
     { 
      dbTransaction.Dispose(); 
     } 
    } 


    /// <summary> 
    /// A method to allow the caller to decide how the SQL statements are called as part of a transaction 
    /// </summary> 
    public abstract void ExecuteSql(IDatabaseConnectivityObjectBasicResponse databaseConnectivityObject, DbTransaction dbTransaction); 
} 

La méthode override

public override void ExecuteSql(IDatabaseConnectivityObjectBasicResponse databaseConnectivityObject, DbTransaction dbTransaction) 
    { 
     //oracle 
     List<string> transactions = new List<string> 
      { 
       "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (1, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))", 
       "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (2, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))", 
       "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (3, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))", 
       "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (4, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))", 
       "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (5, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))", 
       "INSERT INTO TMA_NOT_TO_ENTITY_QUEUE (RECEIVED_NOTICE_ID, NOTICE_TEXT, STATE_ID, TIME_RECEIVED) VALUES (6, 'This is a notice', 1, to_date('2012/08/15', 'yyyy/mm/dd'))" 
      }; 

     databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = databaseConnectivityObject.DBFactoryDatabaseConnection.BeginTransaction(); 

     foreach (var transaction in transactions) 
     { 
      databaseConnectivityObject.DBFactoryDatabaseCommand.CommandText = transaction; 
      databaseConnectivityObject.DBFactoryDatabaseCommand.CommandType = CommandType.Text; 
      databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = dbTransaction; 
      databaseConnectivityObject.DBFactoryDatabaseCommand.ExecuteNonQuery(); 
     } 
    } 

La méthode d'appel

public void RunTransaction() 
     { 
     IDatabaseConnectivityObjectBasicResponse databaseConnectivityObject = new DbProviderFactoryConnectionBasic(); 

     DoTransaction(databaseConnectivityObject); 
     } 

La méthode d'essai

[TestMethod()] 
    public void RunTransactionTest() 
    { 
     TmaNoticeToClusteredEntityValidation target = new TmaNoticeToClusteredEntityValidation(BindVariables, SqlFactory, Dialect); 
     target.RunTransaction(); 
     Assert.Inconclusive("A method that does not return a value cannot be verified."); 
    } 

Répondre

2

Il se trouve que le problème était en fait que je l'appelais BeginTransaction deux fois() sur l'objet de connexion. Cela a été résolu en supprimant databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = databaseConnectivityObject.DBFactoryDatabaseConnection.BeginTransaction(); de la méthode de remplacement.

0

omettre Juste cette ligne sur override

databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = databaseConnectivityObject.DBFactoryDatabaseConnection.BeginTransaction(); 

Et changer cette

databaseConnectivityObject.DBFactoryDatabaseCommand.Transaction = dbTransaction; 

Pour

databaseConnectivityObject.DBFactoryDatabaseCommand.Connection= databaseConnectivityObject.DBFactoryDatabaseConnection; 
Questions connexes