Yanıtlar:
İşte kod pasajı:
using System.Transactions;
....
using (var transactionScope = new TransactionScope())
{
DoYourDapperWork();
transactionScope.Complete();
}
System.Transactions
Varsayılan olarak referansta bulunulmadığından montaja referans eklemeniz gerektiğini unutmayın .
Dispose()
yöntemde otomatik olarak yapar . Eğer Complete()
çağrılmadıysa, işlem geri alınır alır.
TransctionScope
Bu cevabı seçmeniz durumunda bloğun içinde bağlantı açılmalıdır .
İşlemi doğrudan bağlantıdan alarak daha sezgisel bir yaklaşım kullanmayı tercih ettim:
// 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()
Execute
Gerekli olduğundan, işlemi bir parametre olarak dahil etmek iyi bir noktadır .
TransactionScope
Dapper yalnızca ADO.NET komutlarını çalıştırdığı için kullanabilmeniz gerekir .
using (var scope = new TransactionScope())
{
// insert
// insert
scope.Complete();
}
Tüm tablolarınızın tek bir veritabanında olduğu göz önüne alındığında, TransactionScope
buradaki bazı cevaplarda önerilen çözüme katılmıyorum . Bu yanıta bakın .
TransactionScope
genellikle dağıtılmış işlemler için kullanılır; farklı veri tabanlarını kapsayan işlemler farklı sistemlerde olabilir. Bu, işletim sistemi ve SQL Server üzerinde bazı yapılandırmalara ihtiyaç duyar ve bunlar olmadan çalışmaz. Tüm sorgularınız tek bir veritabanı örneğiyle ilgiliyse bu önerilmez.
Ancak, tek bir veritabanıyla, kodu kontrolünüz altında olmayan işleme dahil etmeniz gerektiğinde bu yararlı olabilir. Tek veritabanı ile özel konfigürasyonlara da ihtiyaç duymaz.
connection.BeginTransaction
tek bir veritabanına karşı işlem (C #, VB.NET vb.) uygulamak için ADO.NET sözdizimidir. Bu, birden çok veritabanında çalışmaz.
Yani, connection.BeginTransaction()
daha iyi bir yol.
İşlemi gerçekleştirmenin daha iyi yolu bile bu cevapta açıklandığı gibi UnitOfWork'ü uygulamaktır .
TransactionScope
OP'nin istediği için verimsiz olanı kullanmayı önerir . Bunun TransactionScope
birçok durumda iyi bir araç olduğuna katılıyorum ; ama bu değil.
Daniel'in cevabı benim için beklendiği gibi çalıştı. Tamlık için, burada bir işlem kapsamı ve zarif kullanarak kaydetme ve geri almayı gösteren bir snippet var:
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
yöntemin birinci veya ikinci olarak adlandırıldığını, sadece iki kez çağrıldığını anlatmaya çalışmadım . "İkinci kez elden çıkarmak istemenin zararlı olmadığı" noktasına gelince, bu büyük bir varsayım. Dokümanların ve gerçek uygulamaların çoğu zaman uyuşmadığını öğrendim. Ancak Microsoft'un sözünü istiyorsanız: msdn.microsoft.com/en-us/library/…