2009-10-25 13 views
5

Tego wieczora zbierałem wiedzę, próbując przezwyciężyć 4 lata złych praktyk programistycznych z powodu firmy, dla której pracowałem. Jedną z rzeczy, które ostatnio natknąłem się na System.Transactions. Po przeczytaniu o nich przez ostatnie kilka godzin, myślę, że mam odpowiednie pojęcie o tym, jak działają i dlaczego chciałbyś z nich skorzystać. Jednak wszystkie przykłady, na które patrzyłem, pokazują, że wbudowany T-SQL jest wywoływany z poziomu transakcji.System miksowania. Transakcje z SqlTransactions

ja dość dużo stosowanie procedur przechowywanych wyłącznie podczas wykonywania dostępu do bazy danych, a wszystkie istniejące procedury przechowywane są owinięte w swoich SqlTransactions. Wiesz, używając "Rozpocznij tran", a następnie cofnij lub popełnij. Jeśli zapisany proces wywoła inny zapisany proces, to również tworzy transakcję, a komunikaty bańki się, aż zewnętrzna albo się wycofa, albo wycofa. Działa świetnie.

Tak więc moje pytanie brzmi, czy chciałem zacząć używać System.Transactions w moim kodzie - dla prostych celów monitorowania kolejnych zadań bazy danych, które nie mogą być zagnieżdżone w pojedynczej przechowywanej procedurze - jak to działa z istniejących SqlTransactions mam już w moich przechowywanych procs?

Czy użycie System.transactions w moim kodzie wystarczy dodać jeszcze jedną warstwę ochrony, zanim zostanie faktycznie zatwierdzona, lub dlatego, że jestem jawnie zobowiązująca się w moim SqlTransaction - czy dane będą utrwalane niezależnie od popełnienia lub wycofania w oparciu o kod transakcja?

+0

Przyjęta odpowiedź na to pytanie jest błędna. Korzystanie z transakcji Sql w System.Transaction powoduje niezamierzone zachowanie (a mianowicie transakcja Sql NIE uczestniczy w zewnętrznej System.Transaction!) Wykonanie tego skutecznie neutralizuje transakcję. –

+0

Dziękuję, że wykonałeś te poprawki, Bill. 7 lat później i nie pamiętam nawet, czy w końcu zaimplementowałem coś, co tego wymagało, ale dobrze jest mieć poprawną odpowiedź zaznaczoną. :) – WesleyJohnson

Odpowiedz

4

Nie, System.Transactions i transakcje Sql nie mieszać.

Cytuję: "Nie mieszaj ich" z następującego artykułu MSDN: https://msdn.microsoft.com/en-us/library/ms973865.aspx.

transakcje SQL nie biorą udziału na zewnętrznej transakcji systemowych tak, jak chcesz im. Transakcje Sql, które zawiedą lub wycofają, nie spowodują innych działań w System.Transaction w celu wycofania.


Ten przykład pokazuje zjawiska:

using (var tx = new TransactionScope()) 
{ 
    using (var con = new SqlConnection($"{connectionstring}")) 
    { 
     con.Open(); 

     using (var com = new SqlCommand($"set xact_abort on; begin transaction; INSERT INTO dbo.KeyValueTable VALUES ('value1', '{Guid.NewGuid()}'); rollback;", con)) 
     { 
      // This transaction failed, but it doesn't rollback the entire system.transaction! 
      com.ExecuteNonQuery(); 
     } 

     using (var com = new SqlCommand($"set xact_abort on; begin transaction; INSERT INTO dbo.KeyValueTable VALUES ('value2', '{Guid.NewGuid()}'); commit;", con)) 
     { 
      // This transaction will actually persist! 
      com.ExecuteNonQuery(); 
     } 
    } 
    tx.Complete(); 
} 

Po uruchomieniu tego przykładu w pustym magazynie danych należy zauważyć, że zapisy z drugiej operacji SQL są rzeczywiście popełnione, gdy struktura C# kod sugerowałby, że nie powinny.


Mówiąc prościej, nie należy ich mieszać. Jeśli aranżujesz wiele transakcji Sql w aplikacji, powinieneś po prostu użyć System.Transactions. Niestety oznaczałoby to usunięcie kodu transakcji ze wszystkich przechowywanych procedur, ale niestety, jest to konieczne, ponieważ w przypadku modelu mieszanego nie można zagwarantować integralności danych.

+0

Dziękuję, zmieniłem zaakceptowaną odpowiedź. – WesleyJohnson

+0

Co się stanie, jeśli do SqlCommand została użyta jawna transakcja ADO.Net i że transakcja ta została zarejestrowana w transakcji XA (lub czy jest to nawet możliwe)? Czy to anulowałoby transakcję XA? – STLDeveloper

-1

Działa dobrze, jeśli wszystkie wewnętrzne transakcje w przechowywanych procach są zatwierdzone, wszystko zostanie zatwierdzone. Jeśli jeden z nich się wycofa, wszystko w obrębie zewnętrznej transkacji zostanie wycofane. Czysta magia. :)

+0

Doskonały. Tego właśnie oczekiwałem i wydawało mi się logiczną odpowiedzią, po prostu nie chciałem tego zakładać. Bardzo doceniane. – WesleyJohnson

+0

To jest zdecydowanie błędne. Zobacz: https://msdn.microsoft.com/en-us/library/ms973865.aspx –

+0

Zaakceptowana odpowiedź została zmieniona. :) – WesleyJohnson