Dapper + Oracle + TransactionScope = La transaction a été abandonnée

c# dapper odp.net transactionscope

Question

J'ai regardé autour de moi mais je n'ai pas trouvé de solution appropriée (ou satisfaisante pour moi) pour résoudre un problème que nous rencontrons.

J'utilise les pilotes Dapper et ODP.NET 12 Managed. Le problème n'est pas rencontré lorsque TransactionScope n'est pas utilisé.

Lors de l'exécution de commandes sous une portée de transaction, j'obtiens une erreur "Transaction a abandonnée" via l'exception TransactionAbortedException.

Comportements observés:

1) TransactionAbortedException est levée si et seulement si la transaction est terminée et que le TransactionScope est supprimé. Le moment où l'exception est lancée est pendant l'élimination.

2) Malgré l’exception, le concept de transaction fonctionne réellement! Une fois Complete () appelé, les modifications sont validées dans la base de données.

Voici l'extrait de code.

// Conn string: "Data Source=OraDB;Persist Security Info=True;User ID=userxxx;Password=passwordxxx;"   providerName="Oracle.ManagedDataAccess.Client
// Note: GetDbFactory().Create() returns a DbConnection object
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
using (var dbConn = GetDbFactory().Create())
{
    foreach (MyDTO dto in dtoList)
    {
        var tableDAO= new TableDAO(dbConn);
        MyEntity entity = new MyEntity()
        {
            Field1 = dto.Field1,
            Field2 = dto.Field2
        };
        tableDAO.AddOrUpdate(entity);
     }
     // Commit changes
     scope.Complete();
}

// This method is under the DAO class
public void AddOrUpdate(MyEntity entity)
{
    // Verify arguments
    entity.AsArgumentThrowExceptionIfNull("entity");
    // build param

    OracleDynamicParameters parameters = new OracleDynamicParameters();

    parameters.Add("P_FIELD1", entity.Field1);
    parameters.Add("P_FIELD2", entity.Field2);

    // execute SP
    dbConnection.Execute("PRC_MY_ENTITY_ADDORUPDATE", parameters, commandType: CommandType.StoredProcedure);
}//-- end AddOrUpdate()

================================================== ================
MISE À JOUR (09-avr.-15)

J'ai changé mon approche et utilise pour l'instant le modèle suivant pour Oracle. Notre code traite des connexions à la fois avec Oracle et SQL Server. Je préférerais donc que le modèle de codage soit cohérent, mais tant qu’une solution utilisant Oracle + TransactionScope n’a pas été trouvée, nous utiliserons le modèle ci-dessous pour exécuter la commande Oracle:

using (var dbConnection = dbConnFactory.Create())
{
    // Open db connection
    dbConnection.Open();
    using (var trans = dbConnection.BeginTransaction())
    {
        bool isSuccess = false;
        try
        {
             // Perform DB operations here
             trans.Commit();
             isSuccess = true;
        }
        finally
        {
             if(!isSuccess) trans.Rollback();
        }
   }
}

Réponse acceptée

J'ai recours à BeginTransaction () comme approche finale (voir ma mise à jour dans mon message original). J'ai lu plus sur pourquoi TransactionScope () échouait.

1) ODP.Net favorise la transaction distribuée même en utilisant une seule connexion de base de données lors de la connexion à Oracle 10g et au-dessous ( source ). Et voilà, la base de données à laquelle je me connecte est bien 10g.

2) Oracle MTS Service doit être installé. Ce que je n'avais pas configuré sur ma machine de développement.


Réponse populaire

Je ne vois rien de mal avec ce code. Cependant, si cette boucle est suffisamment longue, la transaction expirera. Vous obtiendrez ensuite l'exception en question lors de la prochaine opération sur la base de données. Je voudrais essayer d'augmenter le délai d'attente - Timeout est une propriété de la classe TransactionScopeOption.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi