2011-08-08 13 views
7

Jak mogę wykonać równoważnik tego? My understanding is that this is impossible with TransactionScopes ale chciałbym osiągnąć równowartość w jakiś inny sposób:Transakcje zagnieżdżone w .NET

klasa Logic działalności:

public bool Bar() 
{ 
    try 
    { 
    using (var tsWork = new TransactionScope()) 
    { 
     ComplicatedDataImportCode(somedata); 
     FlagRecordInDatabaseAsImported(); // this is the same record that's modified in the catch 
     tsWork.Complete(); 
     return true; 
    } 
    catch (DuplicateDataException err) 
    { 
     // if we got here, the above transaction should have rolled back, 
     // so take that same record in the database and update it to "Duplicate". 
     FlagSameRecordInDatabaseAsDuplicate(err.Message); 
    } 

    return false; 
} 

Teraz to działa prawidłowo, dopóki nie upakować wszystko to wewnątrz transakcji (chyba test integracji że chcę wycofać po wykonaniu asserts).

prosty test, aby udowodnić mój punkt widzenia:

public void CanTest() 
{ 
    // Arrange 
    var foo = new Foo(); 

    using (var ts = new TransactionScope()) 
    { 
    // Act 
    var success = foo.Bar(); 

    // Assert 
    if (success) 
    { 
     Assert.That(SomethingThatTestsThatTheDataWasImported); 
    } 
    else 
    { 
     Assert.That(SomethingThatTestsThatTheRecordWasMarkedAsDuplicate); 
    } 

    // Now that we have been able to perform our Asserts, rollback. 

    } 
} 

Ostatecznie kod w Foo.Bar() mogą być modyfikowane w celu dostosowania rozwiązania jednak kod w ComplicatedDataImportCode() nie mogą być modyfikowane dla tego rozwiązania, a to w związku z tym, co naprawdę Muszę się upewnić, czy poprawnie wycofałem scenariusz awarii.

Jeszcze raz rozumiem, że nie można tego zrobić za pomocą programu TransactionScopes, zgodnie z postem, do którego się odwołałem na początku tego pytania. Użyłem tutaj TransactionScopes, aby wskazać, co chciałem zrobić, i szukam najlepszego alternatywnego sposobu wdrożenia tej funkcjonalności.

Odpowiedz

2

Czy to nie musi być obsługiwane przez DBMS, którego używasz?

SQL Server tak naprawdę nie obsługuje transakcji zagnieżdżonych na przykład, jednak z SQL Server można użyć savepoints.

An article Napisałem kilka lat temu na moim blogu.

+1

Serwer SQL obsługuje transakcje zagnieżdżone, a tylko pierwsze "ROLLBACK" zabija wszystkie poziomy. 'COMMIT' przestrzega jednak zagnieżdżenia. – Kratz

+0

Hmm, może jestem pod fałszywym zrozumieniem, że SQL Server obsługuje to. Chciałbym dowiedzieć się więcej. Czytanie twoich linków. +1 na razie ... – Jaxidian

+0

@Kratz: Twój komentarz jest dokładnie moim problemem. Chcę, aby 'ROLLBACK' przywracał tylko tę" wewnętrzną transakcję ", a nie całą całość. – Jaxidian

1

Jeśli można uzyskać blokadę aktywnego połączenia DB, którego używa ComplicatedDataImportCode, należy po prostu uruchomić w tym połączeniu numery BEGIN TRAN i ROLLBACK TRAN.

+0

To jednak nie pozwala na częściowe wycofanie. Rollback skazuje całą transakcję i na tym polega problem. Więc jeśli robię to, co mówisz, wtedy kiedy wykonuję to wycofanie, moje wywołanie 'FlagSameRecordInDatabaseAsDuplicate' nie zadziała, ponieważ jest w ramach tej samej transakcji po wywołaniu przez moją metodę CanTest. – Jaxidian