Badam transakcje i wygląda na to, że dbają o siebie w EF, dopóki przechodzę false
do, SaveChanges()
a następnie dzwonię, AcceptAllChanges()
jeśli nie ma błędów:
SaveChanges(false);
// ...
AcceptAllChanges();
Co jeśli coś pójdzie nie tak? czy nie muszę wycofywać lub gdy transakcja wykracza poza zakres, czy transakcja jest zakończona?
Co stanie się z dowolnymi kolumnami indentiy, które zostały przypisane w połowie transakcji? Zakładam, że jeśli ktoś inny dodał mój rekord po moim, zanim mój się zepsuł, oznacza to, że będzie brakowało wartości tożsamości.
Czy jest jakiś powód, aby używać standardowej TransactionScope
klasy w moim kodzie?
c#
entity-framework
transactions
Mark Smith
źródło
źródło
SaveChanges(fase); ... AcceptAllChanges();
był to wzorzec. Zwróć uwagę, w jaki sposób autor bloga napisał zaakceptowaną odpowiedź na powyższe pytanie - a do tego bloga odwołuje się drugie pytanie. Wszystko się łączy.Odpowiedzi:
Dzięki Entity Framework większość czasu
SaveChanges()
jest wystarczająca. To tworzy transakcję lub powiększa się w dowolnej transakcji otoczenia i wykonuje wszystkie niezbędne prace w tej transakcji.Czasami
SaveChanges(false) + AcceptAllChanges()
parowanie jest przydatne.Najbardziej użytecznym miejscem do tego są sytuacje, w których chcesz dokonać transakcji rozproszonej w dwóch różnych kontekstach.
Tzn. Coś takiego (źle):
Jeśli się
context1.SaveChanges()
powiedzie, ale sięcontext2.SaveChanges()
nie powiedzie, cała rozproszona transakcja zostanie przerwana. Ale niestety Entity Framework już odrzucił zmianycontext1
, więc nie można odtwarzać ani skutecznie rejestrować awarii.Ale jeśli zmienisz kod, aby wyglądał tak:
Podczas gdy wezwanie do
SaveChanges(false)
wysłania niezbędnych poleceń do bazy danych, sam kontekst nie ulega zmianie, więc możesz to zrobić ponownie, jeśli to konieczne, lub możesz przesłuchać,ObjectStateManager
jeśli chcesz.Oznacza to, że jeśli transakcja faktycznie zgłasza wyjątek, który można zrekompensować, albo próbując ponownie, albo rejestrując stan każdego kontekstu
ObjectStateManager
gdzieś.Zobacz mój post na blogu, aby uzyskać więcej.
źródło
SaveChanges(false)
dokonuje faktycznej aktualizacji bazy danych, a jednocześnieAcceptAllChanges()
mówi EF: „Dobra, możesz zapomnieć, które rzeczy trzeba zapisać, ponieważ zostały pomyślnie zapisane”. Jeśli sięSaveChanges(false)
nie powiedzie,AcceptAllChanges()
nigdy nie zostanie wywołany, a EF nadal będzie uważał, że Twój obiekt ma właściwości, które zostały zmienione i muszą zostać zapisane z powrotem w bazie danych.Jeśli używasz EF6 (Entity Framework 6+), zmieniło się to w przypadku wywołań bazy danych do SQL.
Zobacz: http://msdn.microsoft.com/en-us/data/dn456843.aspx
użyj context.Database.BeginTransaction.
Z MSDN:
źródło
throw;
fragment kodu MSDN i wyraźnie wskazałem, że nie jest to oryginał z artykułu MSDN.Rollback()
jest wywoływany na wypadek, gdyby rozmawiał z MySql lub czymś, co nie ma takiego automatycznego zachowania.Ponieważ niektóre bazy danych mogą zgłaszać wyjątek w dbContextTransaction.Commit (), więc lepiej to:
źródło
false
sięcontext.SaveChanges();
, a dodatkowo zadzwonićcontext.AcceptAllChanges();
.