Manière appropriée d'utiliser BeginTransaction avec Dapper.IDbConnection

.net c# dapper idbconnection orm

Question

Quelle est la bonne façon d'utiliser BeginTransaction() avec IDbConnection dans Dapper?

J'ai créé une méthode dans laquelle je dois utiliser BeginTransaction() . Voici le code.

using (IDbConnection cn = DBConnection)
{
    var oTransaction = cn.BeginTransaction();

    try
    {
        // SAVE BASIC CONSULT DETAIL
        var oPara = new DynamicParameters();
        oPara.Add("@PatientID", iPatientID, dbType: DbType.Int32);
        ..........blah......blah............
    }
    catch (Exception ex)
    {
        oTransaction.Rollback();
        return new SaveResponse { Success = false, ResponseString = ex.Message };
    }
}

Quand j'ai exécuté la méthode ci-dessus - j'ai eu une exception -

Opération invalide. La connexion est fermée.

Cela est dû au fait que vous ne pouvez pas commencer une transaction avant que la connexion ne soit ouverte. Donc, quand j'ajoute cette ligne: cn.Open(); , l'erreur est résolue. Mais j'ai lu quelque part que l'ouverture manuelle de la connexion est une mauvaise pratique !! Dapper ouvre une connexion uniquement lorsque cela est nécessaire.

Dans le framework Entity, vous pouvez gérer une transaction à l'aide d'un TransactionScope .

Donc, ma question est la suivante: quelle est la bonne pratique pour gérer les transactions sans ajouter la ligne cn.Open()... dans Dapper ? Je suppose qu'il devrait y avoir un moyen approprié pour cela.

Réponse acceptée

Ouvrir manuellement une connexion n'est pas une "mauvaise pratique"; Dapper fonctionne avec des connexions ouvertes ou fermées par commodité , rien de plus. Un truc commun est celui des personnes ayant des connexions ouvertes, inutilisées, trop longtemps sans jamais les relâcher dans le pool - cependant, ce n'est pas un problème dans la plupart des cas, et vous pouvez certainement le faire:

using(var cn = CreateConnection()) {
    cn.Open();
    using(var tran = cn.BeginTransaction()) {
        try {
            // multiple operations involving cn and tran here

            tran.Commit();
        } catch {
            tran.Rollback();
            throw;
        }
    }
}

Notez que dapper a un paramètre facultatif à transmettre dans la transaction, par exemple:

cn.Execute(sql, args, transaction: tran);

Je suis en fait tenté de faire des méthodes d'extension sur IDbTransaction qui fonctionnent de manière similaire, car une transaction expose toujours .Connection ; cela permettrait:

tran.Execute(sql, args);

Mais cela n'existe pas aujourd'hui.

TransactionScope est une autre option, mais a une sémantique différente: cela pourrait impliquer le LTM ou le DTC, en fonction de ... eh bien, la chance, principalement. Il est également tentant de créer un wrapper autour de IDbTransaction qui n’a pas besoin de la fonction try / catch , mais plutôt du fonctionnement de TransactionScope ; quelque chose comme (cela n'existe pas non plus):

using(var cn = CreateConnection())
using(var tran = cn.SimpleTransaction())
{
    tran.Execute(...);
    tran.Execute(...);

    tran.Complete();
}

Réponse populaire

Vous ne devriez pas appeler

cn.Close();

parce que le bloc using essaiera aussi de se fermer. Pour la partie transaction, oui, vous pouvez également utiliser TransactionScope, car il ne s'agit pas d'une technique liée à Entity Framework. Jetez un oeil à cette réponse SO: https://stackoverflow.com/a/6874617/566608 Il explique comment inscrire votre connexion dans la portée de la transaction. L'aspect important est le suivant: la connexion est automatiquement inscrite dans la transaction IIF, vous ouvrez la connexion dans la portée .




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