2009-08-13 21 views
23

Bir ADO.NET SqlCommand nesnesi oluşturan ve veritabanına kaydedilecek öğelerin bir listesini (SQL Server 2005) döngüler yapan bir "C" yöntemini "devraldım".Refactoring ADO.NET - SqlTransaction vs. TransactionScope

Şu anda, geleneksel SqlConnection/SqlCommand yaklaşımı kullanılır ve her şeyin çalıştığından emin olmak için iki adım (eski girdileri sil, sonra yenilerini ekler) bir ADO.NET SqlTransaction'a sarılır.

using (SqlConnection _con = new SqlConnection(_connectionString)) 
{ 
    using (SqlTransaction _tran = _con.BeginTransaction()) 
    { 
     try 
     { 
     SqlCommand _deleteOld = new SqlCommand(......., _con); 
     _deleteOld.Transaction = _tran; 
     _deleteOld.Parameters.AddWithValue("@ID", 5); 

     _con.Open(); 

     _deleteOld.ExecuteNonQuery(); 

     SqlCommand _insertCmd = new SqlCommand(......, _con); 
     _insertCmd.Transaction = _tran; 

     // add parameters to _insertCmd 

     foreach (Item item in listOfItem) 
     { 
      _insertCmd.ExecuteNonQuery(); 
     } 

     _tran.Commit(); 
     _con.Close(); 
     } 
     catch (Exception ex) 
     { 
      // log exception 
      _tran.Rollback(); 
      throw; 
     } 
    } 
} 

Şimdi, son zamanlarda .NET TransactionScope sınıfının hakkında çok şey okudum, ve merak ettim, tercih edilen yaklaşım burada ne var? Ben

using (TransactionScope _scope = new TransactionScope()) 
{ 
    using (SqlConnection _con = new SqlConnection(_connectionString)) 
    { 
    .... 
    } 

    _scope.Complete(); 
} 
tercih hangi

ve neden kullanarak geçiş yaparak şey (Hassasiyet, hız, güvenilirlik) kazanmak istiyorsunuz?

Marc

cevap

14

Varolan kodunuzu TransactionScope kullanacak şekilde değiştirerek hemen bir şey kazanamazsınız. Sağladığı esneklik nedeniyle gelecekteki geliştirme için kullanmalısınız. Gelecekte ADO.NET çağrıları dışındaki işlemlerin bir işleme dahil edilmesini kolaylaştıracaktır.

BTW, gönderdiğiniz örnekte, SqlCommand örneklerinin using blokları içinde olmalıdır.

+0

Tamam, teşekkürler John - ve evet, haklısın - bu örnek() blokları (henüz!) Kullanarak SqlCommand'a sahip değil - bu iş devam ediyor :-) –

+0

re: SQLCommand'ı kullanarak, var mı? çöp toplama dışında, örneğin: SQLConnection için Dispose() Close() yöntemini çağırır, Dispose() herhangi bir SQLCommand yöntemini çağırır? –

+3

Eğer bir sınıf 'IDisposable'ı uygularsa ve bu sınıfın bir örneğini oluşturursanız, o zaman Dispose'ı çağırmalısınız. Bunu yapmanın en basit yolu bir 'using' bloğu ile. Her zaman birini uygulamak alışkanlığına girmek en iyisi. –

9

Microsoft işlem kapsamı kullanılmasını önerir:

http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx

temel fikir şu işlem kapsamı sizin için "ortam işlem bağlam" yönetecek olduğunu. Bir veritabanına konuşarak başlarsınız, bir sql işleminiz var, daha sonra 2 numaralı veritabanıyla konuşursunuz ve işlem dağıtılmış bir işleme yükseltilir.

İşlem kapsamı sizin için çalışır, böylece sıhhi tesisattan ziyade sistemin işlevselliğine konsantre olabilirsiniz.

DÜZENLEME

o kapsamda bir işlem kapsamı her şeyi kullanmak işlem kapsamındadır. Bu nedenle, komutu bir komutla bağladığınız bir kod satırı kaydedin. Bu olası bir hata kaynağıdır, mesela 1000'de bu çizginin unutulduğu bir şans varsa, kaç tane eksiksiniz.

DÜZENLEME 2

aşağıda Triynko üzerinde yorum ile Anlaştı. Ancak, Entity Framework kullanıyoruz, EF bir işlemi otomatik olarak kapatacak ve bir işlemi bir araya getirmek için bir bağlantıyı yeniden açacaktır. Bağlantıyı fiziksel olarak daha fazla kapatmaz, bağlantı havuzuna bırakır ve yenisi ile aynı olabilir veya farklı olabilir.

+0

Tamam ,. bunun için teşekkürler. Ancak, ADO.NET gömülü işlemler yerine TransactionScope() işlevini kullanmak için her şeyi (sadece bu bir örnek değil) yeniden düzenlerseniz, herhangi bir şekilde yararlanabilir miyim? Sadece çabanın buna değip değmeyeceğini sormak - bununla ne kazanırım? –

+8

"Bir işlem kapsamı kullandığınızda, bu kapsamdaki her şey işlem tarafından karşılanır." Hayır, her şey kapalı değil. Yalnızca kapsamda belirtilen bağlantılarda verilen komutlar kapsamdan etkilenir. Bağlantılar, kapsamda açılmışsa otomatik olarak kapsam dahilindedir, aksi halde zaten açılmış olan bağlantılar, SqlConnection.EnlistTransaction çağrılarak oluşturulduktan sonra kapsamda manuel olarak listelenmelidir. Örneğin, bağlantınızı açarsanız, işlem kapsamını oluşturursanız ... komutlarınızdan hiçbiri işlemde yer almayacaktır. – Triynko

+0

@Triynko: İlgili MSDN makalesine yaptığınız yorum harika! – abatishchev

6

Sadece İşlem Kapsamı'nı kullanmayı unutmayın, çünkü DTC, Güvenlik Duvarı vb. Gibi Sunucuda yapmamız gereken pek çok ayar yapmamız gerektiğinden dolayı çok fazla sorun olacaktır. Bu yüzden SqlTransaction'ı kullanmanızı tavsiye ederim.

7

TransactionScope'u tercih ederim. Her senaryoda mükemmel çalışmaz, ancak tanımladığınızda, daha iyi bir çözümdür.

Benim akıl: İşlem içinde

  1. Askere otomatik
  2. bir İstisna durumunda
  3. İşlem geri alma sonucu biraz daha az kod ve genellikle,

Birlikte otomatiktir daha sağlam tasarım, sistem benim için bazı detayları ele alıyor; Hatırlamam gereken bir şey daha az. Buna ek olarak, şeffaf İşlem kaydı, DAL'nizde çok sayıda iç içe geçmiş yönteminiz olduğunda özellikle yararlı olabilir. Ancak, işleminizin yanlışlıkla DTC gerektiren dağıtılmış birine dönmemesine dikkat etmeniz gerekir. Aynı DB'ye işaret etseler bile, birden çok SqlConnections kullanırsanız bu durum oluşabilir.

2

Tamam, belki bunun için çok geç ... ama şimdi daha iyi görüntü beri neyse, benim akımla zorluklar bir çok yaptıktan sonra

... ilgilenenler için bunu yazmak olacaktır Ben TransactionScope lehine değiştirebilir SqlTransaction tabanlı bir yaklaşım, ben TransactionScope ana avantajı iş avantajı çok Kolay İş Katmanı kullanılabilir.

2

Ayrıca geç ... Veritabanı iç içe geçmiş işlemleri desteklemese bile, iş katmanında kolayca "iç içe" işlemler gerçekleştirebilirsiniz. .NET, iç içe geçirmeyi kontrol eder ve bir veritabanı işlemini (en azından SQL Server 2008+ durumunda) kullanarak biter. Bu, daha büyük bir işlemin parçası olarak, veri erişim kodunu orijinal amacının dışında yeniden kullanmayı çok daha kolay hale getirir.