Czy instrukcja using wycofa transakcję bazy danych, jeśli wystąpi błąd?

83

Mam IDbTransaction w instrukcji using, ale nie jestem pewien, czy zostanie ona wycofana, jeśli w instrukcji using zostanie zgłoszony wyjątek. Wiem, że instrukcja using wymusi wywołanie metody Dispose () ... ale czy ktoś wie, czy to samo dotyczy Rollback ()?

Aktualizacja: Czy muszę również jawnie wywoływać Commit (), tak jak poniżej, czy też zajmie się tym również instrukcja using?

Mój kod wygląda mniej więcej tak:

using Microsoft.Practices.EnterpriseLibrary.Data;

...

using(IDbConnection connection = DatabaseInstance.CreateConnection())
{
    connection.Open();

    using(IDbTransaction transaction = connection.BeginTransaction())
    {
       //Attempt to do stuff in the database
       //potentially throw an exception
       transaction.Commit();
    }
}
mezoid
źródło
3
Cześć, aby wyjaśnić przypadek „zatwierdzenia”. Oczywiście jest to obowiązkowe, ponieważ using () {} po prostu wywołuje metodę Dispose (). Klasa Transaction.Dispose nie mógł wiedzieć, czy powinien on popełnić albo wyrzucić, jeśli był Commit także automatyczne :)
Manitra Andriamitondra

Odpowiedzi:

104

Metoda Dispose dla klasy transakcji wykonuje wycofanie, podczas gdy klasa Oracle nie. Więc z punktu widzenia transakcji jest to zależne od implementacji.

Z usingdrugiej strony instrukcja obiektu połączenia zamknęłaby połączenie z bazą danych lub zwróciłaby połączenie z pulą po zresetowaniu. W każdym przypadku nierozliczone transakcje należy wycofać. Dlatego wyjątek nigdy nie pozostawia aktywnej transakcji.

Również tak, powinieneś zadzwonić Commit()wyraźnie.

Sedat Kapanoglu
źródło
Będzie, nawet raz to przetestowałem, jawnie zgłaszając wyjątek.
Paweł Krakowiak
1
To jest niesamowite, ale czy działa z innymi implementacjami IDbTransaction, jeśli używasz go do kompatybilności między bazami danych?
Matt Hamilton,
4
@mezoid: Commit nigdy nie nastąpi automatycznie. @matt: Powinni, zgodnie z projektem.
Sedat Kapanoglu
1
@MattHamilton, dokładnie tak, jak powiedział ssg. Sprawdziłem źródło złącza .net MySQL, zrobili to samo, jak pokazano powyżej. Rollbackjest wezwany Dispose! :)
nawfal
1
Jeśli używasz System.Data.OracleConnection, nie cofnie się on przy usuwaniu. A przynajmniej dla nas tak nie jest.
Medinoc,
20

Musisz wywołać commit. Instrukcja using nic dla ciebie nie zrobi.

jhale
źródło
5
Tak, użycie wywoła Dispose przy wyjściu, co spowoduje wywołanie Rollback, a nie Commit.
podziw
4

Uważam, że jeśli istnieje wyjątek, który Commit()nigdy nie został wywołany, transakcja zostanie automatycznie wycofana.

Tommy Hui
źródło
Tak, to jest moje zrozumienie. Transakcja trwa do momentu wywołania zatwierdzenia lub zakończenia połączenia. W tym momencie dziennik transakcji jest faktycznie aktualizowany zmianami lub wycofywany w przypadku zamkniętego połączenia (wiesz, że nigdy nie otrzymasz zatwierdzenia z zamkniętego połączenia;)).
Mike,