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?

Author: Liam, 2009-05-03

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ś.

Zobacz mój blog post więcej.

 431
Author: Alex James,
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
        } 
    } 
} 
 101
Author: user3885816,
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(); 
    } 
  } 
} 
 -4
Author: eMeL,
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