Dapper.net ile işlemler nasıl kullanılır?


106

Birden çok tabloda birden çok insert deyimi çalıştırmak istiyorum. Dapper.net kullanıyorum. Dapper.net ile işlemleri halletmenin herhangi bir yolunu görmüyorum.

Lütfen işlemlerin nasıl kullanılacağına dair fikirlerinizi dapper.net ile paylaşın.

Yanıtlar:


107

İşte kod pasajı:

using System.Transactions;    
....    
using (var transactionScope = new TransactionScope())
{
    DoYourDapperWork();
    transactionScope.Complete();
}

System.TransactionsVarsayılan olarak referansta bulunulmadığından montaja referans eklemeniz gerektiğini unutmayın .


7
Hatayı açıkça geri almak gerekiyor mu yoksa System.Transactions bunu otomatik olarak ele alıyor mu?
Norbert Norbertson

6
@NorbertNorbertson bunu Dispose()yöntemde otomatik olarak yapar . Eğer Complete()çağrılmadıysa, işlem geri alınır alır.
the_joric

4
Başka bir cevaptan dolayı bahsetmeye değer ( stackoverflow.com/a/20047975/47672 ): TransctionScopeBu cevabı seçmeniz durumunda bloğun içinde bağlantı açılmalıdır .
0x49D1

2
Ayrıca bkz. ( Stackoverflow.com/a/20047975/444469 ) - DoYouDapperWork (Execute, Query, vb.) Parametrelerde işleme ihtiyaç duyar.
Matthieu

Bir sorun varsa geri alma otomatik olarak çağrılıyor mu?
gandalf

91

İş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();
}

@ANeves: bu seferki çünkü Eh, muhtemelen farklı Zarif çerçeveler kullanıyorsanız: github.com/StackExchange/dapper-dot-net
andrecarlucci

25
.begintransaction'dan önce connection.open () 'i çağırmak zorunda
Zamansız

İşlem kapsamı içinde bağlantıyı açmadığınız sürece, bir bağlantı otomatik olarak transactioncope'a kaydedilmez. GetOpenConnection bir şekilde işlem kapsamı içinde kendini sihirli bir şekilde açarsa kodunuzun nasıl çalıştığını bilmiyorum, ancak açmayacağına bahse girerim
Erik Bergstedt

@ErikBergstedt, bağlantının ancak biz onu aradıktan sonra açılması gerektiğini mi söylüyorsunuz ? Durum böyleyse, bu uzatma yöntemi işlemin yanlış kullanımını teşvik ederdi. (IMO, "bağlantı zaten açıldıktan sonra işlem açılamaz" bile .BeginTransaction()
atmalıdır

2
ExecuteGerekli olduğundan, işlemi bir parametre olarak dahil etmek iyi bir noktadır .
Arve Systad

19

TransactionScopeDapper yalnızca ADO.NET komutlarını çalıştırdığı için kullanabilmeniz gerekir .

using (var scope = new TransactionScope())
{
   // insert
   // insert
   scope.Complete();
}

8

Tüm tablolarınızın tek bir veritabanında olduğu göz önüne alındığında, TransactionScopeburadaki bazı cevaplarda önerilen çözüme katılmıyorum . Bu yanıta bakın .

  1. TransactionScopegenellikle 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.

  2. connection.BeginTransactiontek 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 .


4
TransactionScope'tan yararlanmak için birden fazla veritabanına ihtiyaç yoktur. Özellikle faydalı olan, ortam olmasıdır. Bir işlemde sahip olmadığınız veya değiştiremeyeceğiniz kodu paketlemek için harikadır. Örneğin, daha sonra geri dönmek istediğiniz yerde veritabanı çağrıları yapan birim / entegrasyon testi kodu olduğunda büyük etki için kullanılabilir. Bir TransactionScope'u yüzdürmeniz, kodu test etmeniz ve temizleme testi sırasında imha etmeniz yeterlidir.
Larry Smith

3
@LarrySmith: Kabul edildi; ama soru bununla ilgili değil. OP, bir işlemde birden çok tablo eklemek istediğini söylüyor. Kabul edilen cevap da dahil olmak üzere bazı cevaplar, TransactionScopeOP'nin istediği için verimsiz olanı kullanmayı önerir . Bunun TransactionScopebirçok durumda iyi bir araç olduğuna katılıyorum ; ama bu değil.
Amit Joshi

5

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 

2
@usr, kişisel tercihlere bağlı. İlk kez bir şeylerin ters gittiğini bilmeyi ve günlük ifadelerini çöp olarak görmemeyi tercih ederim. Ayrıca, cevabım, zarif işlemlerden yararlanmanın bir yolunu göstererek hala değer veriyor
Sudhanshu Mishra

@CodeNaked, önce orada sipariş yanlış. Bir istisna varsa önce catch bloğu, ardından kullanım kapsamının sonu vurulur. İkinci olarak, bu yanıta ve başvurulan MSDN belgesine bakın: stackoverflow.com/a/5306896/190476 ikinci kez dispose çağrısı yapmak zararlı değildir, iyi tasarlanmış bir nesne ikinci çağrıyı yok sayar. Olumsuz oy haklı değil!
Sudhanshu Mishra

@dotnetguy - Hangi Disposeyö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/…
CodeNaked

3
Öyleyse, olumsuz oy kullanma nedeniniz bir kod analizi uyarısı mı? Bu, yanıtı yanlış veya yanıltıcı yapmaz - işte o zaman olumsuz oy uygundur. Neden işlevselliği korurken yanıtı düzenlemiyor ve daha iyi bir çözüm önermiyorsunuz? Yığın taşması tamamen yardım ve yapıcı eleştiri ile ilgilidir.
Sudhanshu Mishra
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.