Używając Transactions or SaveChanges (false) and AcceptAllChanges ()?
Badałem transakcje i wygląda na to, że dbają o siebie w EF tak długo, jak przechodzę false
do SaveChanges()
, a następnie wywołuję AcceptAllChanges()
, Jeśli nie ma błędów:
SaveChanges(false);
// ...
AcceptAllChanges();
A jeśli coś pójdzie źle? czy nie muszę wycofywać lub, jak tylko moja metoda wyjdzie z zakresu, czy transakcja została zakończona?
Co się dzieje z kolumnami indentiy, które zostały przypisane w połowie transakcji? Przypuszczam, że jeśli ktoś jeszcze dodał płytę po mojej, zanim moja poszła źle oznacza to, że nie będzie brakującej wartości tożsamości.
Czy Jest jakiś powód, aby używać standardowej klasy TransactionScope
w moim kodzie?
3 answers
Ze strukturą encji przez większość czasu SaveChanges()
jest wystarczająca. Tworzy to transakcję lub włącza się do dowolnej transakcji otoczenia i wykonuje wszystkie niezbędne prace w tej transakcji.
Czasami jednak parowanie SaveChanges(false) + AcceptAllChanges()
jest przydatne.
Najbardziej przydatnym miejscem do tego jest sytuacja, w której chcesz wykonać transakcję rozproszoną w dwóch różnych kontekstach.
Czyli coś takiego (źle):
using (TransactionScope scope = new TransactionScope())
{
//Do something with context1
//Do something with context2
//Save and discard changes
context1.SaveChanges();
//Save and discard changes
context2.SaveChanges();
//if we get here things are looking good.
scope.Complete();
}
If context1.SaveChanges()
successful but context2.SaveChanges()
fails the Cała rozproszona transakcja zostaje przerwana. Ale niestety struktura encji odrzuciła już zmiany na context1
, więc nie możesz odtworzyć ani skutecznie zarejestrować błędu.
Ale jeśli zmienisz kod, aby wyglądał tak:
using (TransactionScope scope = new TransactionScope())
{
//Do something with context1
//Do something with context2
//Save Changes but don't discard yet
context1.SaveChanges(false);
//Save Changes but don't discard yet
context2.SaveChanges(false);
//if we get here things are looking good.
scope.Complete();
context1.AcceptAllChanges();
context2.AcceptAllChanges();
}
Podczas gdy wywołanie SaveChanges(false)
wysyła niezbędne polecenia do bazy danych, sam kontekst nie jest zmieniany, 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 rzuca wyjątek, który możesz zrekompensować, przez ponowne wypróbowanie lub zalogowanie stanu każdego kontekstu ObjectStateManager
gdzieś.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-20 06:03:54
Jeśli używasz EF6 (Entity Framework 6+), to zmieniło się dla wywołań bazy danych do SQL.
Zobacz: http://msdn.microsoft.com/en-us/data/dn456843.aspx
Użyj kontekstu.Baza danych./ Align = "left" /
Z MSDN:
using (var context = new BloggingContext()) { using (var dbContextTransaction = context.Database.BeginTransaction()) { try { context.Database.ExecuteSqlCommand( @"UPDATE Blogs SET Rating = 5" + " WHERE Name LIKE '%Entity Framework%'" ); var query = context.Posts.Where(p => p.Blog.Rating >= 5); foreach (var post in query) { post.Title += "[Cool Blog]"; } context.SaveChanges(); dbContextTransaction.Commit(); } catch (Exception) { dbContextTransaction.Rollback(); //Required according to MSDN article throw; //Not in MSDN article, but recommended so the exception still bubbles up } } }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-03 12:40:23
Ponieważ niektóre bazy danych mogą rzucać wyjątek w dbContextTransaction.Commit () więc lepiej to:
using (var context = new BloggingContext())
{
using (var dbContextTransaction = context.Database.BeginTransaction())
{
try
{
context.Database.ExecuteSqlCommand(
@"UPDATE Blogs SET Rating = 5" +
" WHERE Name LIKE '%Entity Framework%'"
);
var query = context.Posts.Where(p => p.Blog.Rating >= 5);
foreach (var post in query)
{
post.Title += "[Cool Blog]";
}
context.SaveChanges(false);
dbContextTransaction.Commit();
context.AcceptAllChanges();
}
catch (Exception)
{
dbContextTransaction.Rollback();
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 02:19:31