2012-07-10 11 views
6

Jesteśmy w trakcie stopniowego zastępowania starego kodu dostępu do danych według struktury encji (4.3.1). W niektórych przypadkach nie możemy uniknąć korzystania z obu sposobów dostępu do danych w jednej jednostce pracy. Najlepiej, żeby to się odbywało w jednej transakcji. Jednak stary kod używa SqlTransaction s, który wywołuje Commit(), gdy jednostka pracy jest wykonywana, a EF zarządza własnymi transakcjami.Zignoruj ​​SqlTransaction.Commit w ramach TransactionScope

Tak więc pomyśleliśmy o zawijaniu "starego" i "nowego" kodu w TransactionScope. Jednak zatwierdzenie w otoczeniu TransactionScope jest zawsze wykonywane, nawet jeśli TransactionScope nie jest ukończone. Ten fragment kodu ilustruje mój problem:

using (var conn = new SqlConnection("connection string")) 
{ 
    conn.Open(); 
    using (var scope = new TransactionScope()) 
    { 
    using (var tr = conn.BeginTransaction()) 
    { 
     using (var cmd = conn.CreateCommand()) 
     { 
     cmd.Transaction = tr; 
     cmd.CommandText = "some update statement"; 
     cmd.ExecuteNonQuery(); 
     } 
     tr.Commit(); 
    } 
    // In reality the code above is part of a legacy DAL, immutable. 
    // (can't insert SaveChanges before tr.Commit). 
    context.SaveChanges(); 
    if (<all ok>) // pseudo code for exception handling. 
     scope.Complete(); 
    } 
} 

Oświadczenie aktualizacja jest nadal zaangażowana gdy scope.Complete() nie jest trafiony.

Tak więc, jak się wydaje, nie mogę użyć TransactionScope, aby wymusić stary kod dostępu do danych iz kontekstu do wykonania w jednej transakcji. A może istnieje sposób, aby uchylić instrukcję SqlTransaction.Commit?

Wiem, że jest więcej postów tutaj o TransactionScope i SqlTransaction, ale wszyscy (słusznie) twierdzą, że używanie SqlTransaction nie jest konieczne (ani zalecane) podczas korzystania z TransactionScope. Ale nie używanie SqlTransaction nie jest tutaj opcją. Mamy starszą platformę, która zatwierdza własne i nie ma api do podpięcia do mechanizmu transakcji.

+0

Czy masz przynajmniej dostęp do połączenia? –

+0

@LadislavMrnka Nie, oprócz ciągu połączenia w pliku konfiguracyjnym. –

Odpowiedz

7

Instrukcja update jest nadal zatwierdzana, gdy scope.complete() nie zostanie trafiony.

O nie !! TransacationScope nie jest używany .

Auto-zaciągnąć tylko prace, jeśli połączenie jest otwarte po (lub wewnątrz) TransactionScope.

Uruchamianie systemu OpenwewnątrzTransactionScopepowinny rozwiązać ten problem (nawet z transakcją ręcznym?), A połączenie będzie następnie [zwykle] auto-zaciągnąć w kontekście otoczenia TS.

Istniejące połączenie można zarejestrować w zakresie transakcji otoczenia: connection.EnlistTransaction(Transaction.Current).

Alternatywnie, TS można utworzyć z istniejącej transakcji, np. new TransactionScope(transaction), które mogą być lub nie być pomocne tutaj.

Tworzenie ręczną transakcji, jeżeli perfekcyjnie, ale TS (po pułapek są zorientowali się!) Sprawia, że ​​do czynienia z transakcjami prostsze i łatwiejsze .. przynajmniej w większości przypadków :)

Szczęśliwy kodowania!


TS nie jest używany dla "rachunku update".Będzie on nadal [prawdopodobnie] będzie używany dla context.SaveChanges(), ponieważ otworzy on nowe połączenie , które następnie zostanie automatycznie zarejestrowane.

Podałem niektóre opcje powyżej, chociaż nie jestem pewien co do zwykłej "zagnieżdżonej" transakcji. Zobaczenie (zapieczętowanego?) Interfejsu API zastosowanego w kontekście może ujawnić więcej informacji na temat ograniczeń/ograniczeń.

+0

Masz rację! Kiedy kładę "Open" po TS, prowadzi TS. I pomyślałbym, że w rzeczywistości powinno to również nastąpić, ponieważ połączenie jest otwarte w starym szkielecie. Ale nadal zobowiązuje. Będę musiał zagłębić się nieco w to, co się tam dzieje i sprawdzić, czy jedna z twoich sugestii może to naprawić. Dzięki, wrócę do tego. –

+0

To doprowadziło mnie na właściwą drogę. Dowiedziałem się, że stara struktura pozostawia połączenia otwarte dłużej niż powinno. Dlatego nie można używać TransactionScope tak, jak chciałbym, bez zmiany starego kodu - czego bardzo niechętnie robimy. Obawiam się, że musimy. –

Powiązane problemy