La bonne façon d'utiliser BeginTransaction avec Dapper.IDbConnection
Qui 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é méthode ci-dessus - j'ai eu une exception -
Opération non valide. La connexion est fermée.
C'est parce que vous ne pouvez pas commencer une transaction avant la connexion est ouverte. Alors quand j'ai ajouter cette ligne: cn.Open();
, l'erreur est résolue. Mais j'ai lu quelque part que de l'ouvrir manuellement la connexion est mauvaise pratique!! Dapper ouvre une connexion uniquement quand il en a besoin.
Dans le cadre de l'Entité que vous pouvez gérer une transaction à l'aide d'un TransactionScope
.
Donc ma question est qu'est ce qu'une bonne pratique pour gérer des transactions sans l'ajout de la ligne cn.Open()...
dans Dapper ? Je suppose qu'il devrait y avoir un bon moyen pour cela.
Vous devez vous connecter pour publier un commentaire.
Manuellement l'ouverture de la connexion n'est pas "mauvaise pratique"; dapper fonctionne avec ouvert ou fermé connexions commodité, rien de plus. D'un commun gotcha est que les gens ayant des connexions qui sont laissées ouvertes, non utilisé, trop longtemps sans jamais les publier à la piscine - cependant, ce n'est pas un problème dans la plupart des cas, et vous pouvez certainement le faire:
Noter que dapper est un paramètre facultatif pour passer dans la transaction, par exemple:
Je suis en fait tenté pour rendre les méthodes d'extension sur
IDbTransaction
qui fonctionnent de la même façon, depuis une opération toujours expose.Connexion
; cela permettrait:Mais cela n'existe pas aujourd'hui.
TransactionScope
est une autre option, mais ont des sémantiques différentes: cela pourrait impliquer la LTM ou la DTC, selon ... eh bien, la chance, principalement. Il est également tentant de créer un wrapper autour deIDbTransaction
qui n'a pas besoin de latry
/catch
- plus comme la façon dontTransactionScope
œuvres; quelque chose comme (cela n'existe pas):tran.RollBack
? l'opération est-elle pas annulée automatiquement sur les éliminer?Vous ne devez pas appeler
parce que l'utilisation de bloc va essayer de trop près.
Pour la transaction, oui, vous pouvez utiliser TransactionScope, puisqu'il n'est pas une Entité Cadre technique connexe.
Jetez un oeil à cette SORTE de réponse: https://stackoverflow.com/a/6874617/566608
Il expliquera comment inscrire votre connexion dans l'étendue de la transaction.
L'aspect important est: connexion sont automatiquement enrôlé dans la transaction SI vous ouvrez la connexion dans le champ d'application.
Prendre un coup d'oeil à Tim Schreiber solution qui est simple, mais puissant et mis en œuvre en utilisant un modèle de référentiel et a
Dapper Transactions
à l'esprit.La
Commit()
dans le code ci-dessous montre qu'il s'.commit()
lorsque votre requête est justeSELECT
. Alors ne vous inquiétez pas au sujet de la performance!. votre idée sur l'ajout d'un drapeau est sympa, mais en fait, il n'est pas nécessaire. Je l'utilise de cette façon et il fonctionne comme un charme.Nous avons mis en œuvre cette Uow modèle, mais nous avons des problèmes avec les appels asynchrones. Parfois à _transaction.Dispose (), nous recevons La connexion ne prend pas en charge MultipleActiveResultSets.