2015-03-03 16 views
5

W mojej aplikacji mam metoda wygląda następująco:Jak korzystać z transakcji dla różnych kontekstów?

public static bool DoLargeOperation() 
{ 
    bool res = true; 

    res = res && DoFirstSubOperation(); 
    res = res && DoSecondSubOperation(); 
    res = res && DoThirdSubOperation(); 

    return res; 
} 

a każda z metod wewnętrznych wygląda następująco:

public static bool DoFirstSubOperation() 
{ 
    using (var context = new EntityFrameworkContext()) 
    { 
     // data modification. 
     context.SaveChanges(); 
    } 
} 

Na przykład DoFirstSubOperation() i DoSecondSubOperation() zakończona pomyślnie, ale DoThirdSubOperation() zawiedzie. Jak wycofać zmiany wprowadzone przez dwie pierwsze funkcje?

Takie podejście nie przyniosła rezultatów:

using (var transaction = new TransactionScope()) 
{ 
    res = res && DoFirstSubOperation(); 
    res = res && DoSecondSubOperation(); 
    res = res && DoThirdSubOperation(); 
} 

Jedynym rozwiązaniem widzę jest zdefiniowanie kontekstu tak:

public static bool DoLargeOperation() 
{ 
    bool res = true; 

    using (var context = new EntityFrameworkContext()) 
    { 
     using (var transaction = context.Database.BeginTransaction()) 
     { 

      res = res && DoFirstSubOperation(context); 
      res = res && DoSecondSubOperation(context); 
      res = res && DoThirdSubOperation(context); 
      if (res) 
      { 
       transaction.Commit(); 
      } 
      else 
      { 
       transaction.Rollback(); 
      } 
     } 
    } 

    return res; 
} 

Ale jest to dopuszczalne, aby to zrobić? Czy istnieje inne rozwiązanie?

+0

Co nie działało w * tym podejściu * ?. To najbardziej poprawny sposób na osiągnięcie tego, czego szukasz. – abatishchev

+0

Nie cofa zmian w zakończonych operacjach. –

+0

Bez 'scope.Commit()' nie powinien ich faktycznie zatwierdzać. Jak sprawdzić zmiany? Może jesteś w tej samej transakcji? Lub na zewnątrz, powiedz używając Management Studio? – abatishchev

Odpowiedz

5

Tak, to jest poprawny wzór. Przekazanie kontekstu do metod pozwala na ponowne wykorzystanie metod w wielu lokalizacjach, ponieważ kontekst i transakcja będą zarządzane przez wywołującego.

Mimo, że prawdopodobnie najprawdopodobniej przestaniesz przetwarzać kolejne metody, gdy pierwszy z nich się nie powiedzie. Ty też pewnie chce owinąć wezwanie do dzieci w try/catch, tak że każdy wyjątek pozwala wycofywania występuje prawidłowo ...

try 
{ 
    res = DoFirstSubOperation(context); 
    if (res) 
     res = DoSecondSubOperation(context); 
    if (res) 
     res = DoThirdSubOperation(context);  

    if (res) 
     transaction.Commit(); 
    else 
     transaction.Rollback(); 
} 
catch 
{ 
    transaction.Rollback(); 
} 

Jeśli twoje dziecko już metody obsługi wyjątków wtedy można zrezygnować z try/łapać.

+0

Dziękuję! Po prostu upraszczam przykład, aby pokazać tylko istotę. –

Powiązane problemy