Réponses:
Voici l'extrait de code:
using System.Transactions;
....
using (var transactionScope = new TransactionScope())
{
DoYourDapperWork();
transactionScope.Complete();
}
Notez que vous devez ajouter une référence à l' System.Transactions
assembly car il n'est pas référencé par défaut.
Dispose()
méthode. S'il Complete()
n'a pas été appelé, la transaction est annulée.
TransctionScope
bloc using au cas où vous choisiriez cette réponse.
J'ai préféré utiliser une approche plus intuitive en récupérant la transaction directement depuis la connexion:
// This called method will get a connection, and open it if it's not yet open.
using (var connection = GetOpenConnection())
using (var transaction = connection.BeginTransaction())
{
connection.Execute(
"INSERT INTO data(Foo, Bar) values (@Foo, @Bar);", listOf5000Items, transaction);
transaction.Commit();
}
.BeginTransaction()
? Si tel était le cas, cette méthode d'extension favoriserait une mauvaise utilisation de la transaction. (OMI, il devrait même lancer "
Execute
, car cela est nécessaire.
Vous devriez pouvoir l'utiliser TransactionScope
car Dapper n'exécute que des commandes ADO.NET.
using (var scope = new TransactionScope())
{
// insert
// insert
scope.Complete();
}
Étant donné que toutes vos tables sont dans une seule base de données, je ne suis pas d'accord avec la TransactionScope
solution suggérée dans certaines réponses ici. Reportez - vous cette réponse.
TransactionScope
est généralement utilisé pour les transactions distribuées; la transaction couvrant différentes bases de données peut être sur un système différent. Cela nécessite certaines configurations sur le système d'exploitation et SQL Server sans lesquelles cela ne fonctionnera pas. Cela n'est pas recommandé si toutes vos requêtes concernent une seule instance de base de données.
Mais, avec une base de données unique, cela peut être utile lorsque vous devez inclure le code dans une transaction qui n'est pas sous votre contrôle. Avec une base de données unique, il n'a pas non plus besoin de configurations spéciales.
connection.BeginTransaction
est la syntaxe ADO.NET pour implémenter une transaction (en C #, VB.NET, etc.) sur une seule base de données. Cela ne fonctionne pas sur plusieurs bases de données.
Alors, connection.BeginTransaction()
c'est la meilleure façon de procéder.
Même la meilleure façon de gérer la transaction consiste à implémenter UnitOfWork comme expliqué dans cette réponse.
TransactionScope
ce qui est inefficace pour ce que veut OP. Je reconnais que TransactionScope
c'est un bon outil dans de nombreux cas; mais pas ça.
La réponse de Daniel a fonctionné comme prévu pour moi. Pour être complet, voici un extrait de code qui montre la validation et la restauration à l'aide d'une portée de transaction et d'un dapper:
using System.Transactions;
// _sqlConnection has been opened elsewhere in preceeding code
using (var transactionScope = new TransactionScope())
{
try
{
long result = _sqlConnection.ExecuteScalar<long>(sqlString, new {Param1 = 1, Param2 = "string"});
transactionScope.Complete();
}
catch (Exception exception)
{
// Logger initialized elsewhere in code
_logger.Error(exception, $"Error encountered whilst executing SQL: {sqlString}, Message: {exception.Message}")
// re-throw to let the caller know
throw;
}
} // This is where Dispose is called
Dispose
méthode est appelée en premier ou en deuxième, juste qu'elle est appelée deux fois. Quant au fait que "appeler à disposer une deuxième fois n'est pas nuisible", c'est une grande hypothèse. J'ai appris que les documents et les implémentations réelles ne sont souvent pas d'accord. Mais si vous voulez le mot de Microsoft pour cela: msdn.microsoft.com/en-us/library