2011-11-26 8 views
8

Witam Próbuję użyć transakcji wraz z Entity Framework. Przy tak dużej ilości informacji dostępnych online na temat różnych sposobów realizacji transakcji muszę powiedzieć, że jestem nieco zdezorientowany we właściwy sposób. Mam przykładową bazę danych z dwiema tabelami Pracownik i Firma. Tabela Pracownik ma klucz obcy odnoszący się do identyfikatora firmy. Biorąc pod uwagę Chcę zaimplementować transakcję, w której wstawiam rekord do tabeli Company, a następnie rekord do tabeli Employee i chcę to zrobić, aby wpisy były wstawiane tylko wtedy, gdy oba są skuteczne Mam następujący kod.Opis transakcji w strukturze jednostki

public void addCompanyToDatabase() 
    { 
     using (var context = new myTestEntities()) 
     { 
      context.Connection.Open(); //added this as was getting the underlying 
      //provider failed to open 
      using (TransactionScope scope = new TransactionScope()) 
      { 
       try 
       { 
        Company c = new Company(); 
        c.Name = "xyz"; 
        context.Companies.AddObject(c); 
        context.SaveChanges(); 

        //int a = 0; 
        //int b = 5/a; 

        Employee e = new Employee(); 
        e.Age = 15; 
        e.Name = "James"; 
        e.CompanyId = c.Id; 
        context.Employees.AddObject(e); 
        context.SaveChanges(); 

        scope.Complete(); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine("Exception Occurred"); 
       } 
      } 
     } 
    } 

Chciałem wiedzieć, czy to był właściwy sposób realizacji transakcji. Jeśli tak jest, to jakie jest użycie funkcji SaveChanges(false) i . Wszelkie informacje byłyby pomocne.

Odpowiedz

14

W twoim przypadku nie musisz zarządzać żadnym połączeniem lub transakcją: Entity Framework zrobi to za ciebie. Jeśli EF nie zostanie dostarczone z otwartym połączeniem (ale z łańcuchem połączenia), otworzy połączenie i rozpocznie transakcję podczas połączenia z numerem context.SaveChanges(). Gdy coś zawiedzie podczas tego połączenia, transakcja zostanie wycofana.

Innymi słowy, metoda może po prostu wyglądać następująco:

public void addCompanyToDatabase() 
{ 
    using (var context = new myTestEntities()) 
    { 
     Company c = new Company(); 
     c.Name = "xyz"; 
     context.Companies.AddObject(c); 

     Employee e = new Employee(); 
     e.Age = 15; 
     e.Name = "James"; 
     e.CompanyId = c.Id; 
     context.Employees.AddObject(e); 

     // Only call SaveChanges last. 
     context.SaveChanges(); 
    } 
} 
+0

Ma to sens w przypadku mojego przykładu. Czy możesz podać przykład, w którym potrzebowałbym transakcji? a jeśli kod, o którym wspomniałem powyżej, jest sposobem na wdrożenie transakcji? Przypuszczam, że aktualizowanie rekordów w dwóch różnych kontekstach to jeden scenariusz. – nighthawk457

+1

Najczęstszym przypadkiem, który napotkałem, powoduje, że potrzebujesz transakcji, jest to, gdy musisz wielokrotnie wywoływać 'SaveChanges'. Może się to zdarzyć, gdy potrzebujesz (wygenerowanego przez bazę danych) identyfikatora nowego obiektu lub gdy musisz wymusić ORM wykonanie operacji w określonej kolejności (na przykład LINQ do SQL ma tendencję do ponownego porządkowania usuwania po wstawieniu, ale może to spowodować wyjątek ograniczenia bazy danych). – Steven

+3

We wszystkich przypadkach nadal nie ma potrzeby używania 'TransactionScope'. Jeśli potrzebujesz 'TransactionScope', ponieważ potrzebujesz operacji by być atomową w wielu bazach danych, prawdopodobnie masz wadę projektową w swoim systemie. Używam 'TransactionScope's wyłącznie do moich automatycznych testów integracyjnych. Wystarczy rap kodu wywołującego w 'TransactionScope' i możesz upewnić się, że wszystkie zmiany (bazy danych) są wycofywane na końcu testu, bez konieczności zmiany jakiegokolwiek kodu dla tego. – Steven

0

1-to serwis (myślę obsługa transakcji) muszą być run klient wspierać TransactionScope

2 -Usunięcie, gdy masz w swojej aplikacji lub więcej baz danych i chcesz, aby wszystkie bazy danych aktualizowały transakcje (np. Zmieniaj ciąg połączenia twojego kontekstu).

3-Gdy masz bazę danych lepiej użyj SaveChanges(), która wewnętrznie realizuje transakcję.