2009-04-16 14 views
64

Mam fragment kodu, który zawiera wiele wstawek, ale trzeba wykonać metodę submitchanges przed zakończeniem wstawiania w innych tabelach, aby można było uzyskać identyfikator. Szukałem w Internecie i nie mogłem znaleźć sposobu na utworzenie transakcji w linq do sql. Umieściłem komentarze w kodzie, w którym chcę, aby transakcja miała miejsce.Jak utworzyć transakcję LINQ na SQL?

var created = false; 
    try 
    { 
     var newCharacter = new Character(); 
     newCharacter.characterName = chracterName; 
     newCharacter.characterLevel = 1; 
     newCharacter.characterExperience = 0; 
     newCharacter.userUsername = userUsername; 
     newCharacter.characterClassID = ccslst[0].characterClassID; 
     //Open transaction 


      ydc.Characters.InsertOnSubmit(newCharacter); 
      ydc.SubmitChanges(); 

      foreach (var ccs in ccslst) 
      { 
       var cs = new CharacterStat(); 
       cs.statId = ccs.statID;       
       cs.statValue = ccs.statValue; 
       cs.characterID = newCharacter.characterID; 
       ydc.CharacterStats.InsertOnSubmit(cs); 
      }      


      var ccblst = ydc.ClassBodies.Where(cb => cb.characterClassID == newCharacter.characterClassID); 
      foreach (var ccb in ccblst) 
      { 
       var charBody = new CharacterBody(); 
       charBody.bodyId = ccb.bodyId; 
       charBody.bodyPartId = ccb.bodyPartId; 
       charBody.characterID = newCharacter.characterID; 
       ydc.CharacterBodies.InsertOnSubmit(charBody); 
      } 
      ydc.SubmitChanges();  
      created = true; 
     //Commit transaction 
     } 
     catch (Exception ex) 
     { 
      created = false; 
      //transaction Rollback;      
     } 
     return created; 

EDIT: Zapomniałem wspomnieć, że YDC jest mój datacontext

Odpowiedz

65

Wrap całość w TransactionScope. Zadzwoń pod numer transaction.Complete() w miejscu, w którym chcesz dokonać zatwierdzenia. Jeśli kod zostanie zamknięty bez wywołania Complete(), transakcja zostanie wycofana. Jednak po zapoznaniu się z odpowiedzią @ s_ruchit i ponownym sprawdzeniu kodu, prawdopodobnie możesz przepisać to, aby nie wymagać TransactionScope. Pierwszy przykład wykorzystuje kod TransactionScope z niezmienionym kodem. Drugi przykład wprowadza drobne zmiany, ale osiąga ten sam cel.

Miejsce, w którym należy użyć TransactionScope, to odczyt wartości z bazy danych i użycie jej do ustawienia nowej wartości dodawanego obiektu. W takim przypadku transakcja LINQ nie obejmuje pierwszego odczytu, a jedynie późniejszego przesłania nowej wartości. Ponieważ używasz wartości z odczytu, aby obliczyć nową wartość dla zapisu, musisz czytać zawinięty w tę samą transakcję, aby upewnić się, że inny czytelnik nie obliczy tej samej wartości i nie zmieni twojej zmiany. W twoim przypadku robisz tylko zapisy, aby standardowa transakcja LINQ działała.

Przykład 1:

var created = false; 

using (var transaction = new TransactionScope()) 
{ 
    try 
    { 
     var newCharacter = new Character(); 
     newCharacter.characterName = chracterName; 
     newCharacter.characterLevel = 1; 
     newCharacter.characterExperience = 0; 
     newCharacter.userUsername = userUsername; 
     newCharacter.characterClassID = ccslst[0].characterClassID; 

     ydc.Characters.InsertOnSubmit(newCharacter); 
     ydc.SubmitChanges(); 

     foreach (var ccs in ccslst) 
     { 
      var cs = new CharacterStat(); 
      cs.statId = ccs.statID;       
      cs.statValue = ccs.statValue; 
      cs.characterID = newCharacter.characterID; 
      ydc.CharacterStats.InsertOnSubmit(cs); 
     }      

     var ccblst = ydc.ClassBodies.Where(cb => cb.characterClassID == newCharacter.characterClassID); 
     foreach (var ccb in ccblst) 
     { 
      var charBody = new CharacterBody(); 
      charBody.bodyId = ccb.bodyId; 
      charBody.bodyPartId = ccb.bodyPartId; 
      charBody.characterID = newCharacter.characterID; 
      ydc.CharacterBodies.InsertOnSubmit(charBody); 
     } 
     ydc.SubmitChanges();  
     created = true; 

     transaction.Complete(); 
    } 
    catch (Exception ex) 
    { 
     created = false; 
    } 
} 
return created; 

Przykład 2:

try 
    { 
     var newCharacter = new Character(); 
     newCharacter.characterName = chracterName; 
     newCharacter.characterLevel = 1; 
     newCharacter.characterExperience = 0; 
     newCharacter.userUsername = userUsername; 
     newCharacter.characterClassID = ccslst[0].characterClassID; 

     ydc.Characters.InsertOnSubmit(newCharacter); 

     foreach (var ccs in ccslst) 
     { 
      var cs = new CharacterStat(); 
      cs.statId = ccs.statID;       
      cs.statValue = ccs.statValue; 
      newCharacter.CharacterStats.Add(cs); 
     }      

     var ccblst = ydc.ClassBodies.Where(cb => cb.characterClassID == newCharacter.characterClassID); 
     foreach (var ccb in ccblst) 
     { 
      var charBody = new CharacterBody(); 
      charBody.bodyId = ccb.bodyId; 
      charBody.bodyPartId = ccb.bodyPartId; 
      newCharacter.CharacterBodies.Add(charBody); 
     } 
     ydc.SubmitChanges();  
     created = true; 
    } 
    catch (Exception ex) 
    { 
     created = false; 
    } 
+0

Nie wiem o składni, muszę umieścić mojego kodu w tym zakresie: using (TransactionScope ts = new TransactionScope()) { // mój kod } – Drahcir

+0

Dodałem go do kodu i wkleiłem jako przykład. – tvanfosson

+0

Udało się, dziękuję – Drahcir

38

Nie trzeba robić wyraźne Realizacja transakcji podczas korzystania z LINQ to SQL. Wszystkie operacje DB są domyślnie pakowane w transakcję.

Ex:

AppDataContext db = new AppDataContext(); 

<In memory operation 1 on db> 
<In memory operation 2 on db> 
<In memory operation 3 on db> 
<In memory operation 4 on db> 

db.SubmitChanges(); 

Wszystkie operacje między db inicjalizacji DataContext i db.SubmitChanges() są owinięte wokół transakcji bazy danych przez Net zapewnienia bazy danych, aby być spójne i uczciwie własności prowadzonym w poprzek stołów.

Czytaj artykuł Scott Guthriehere: - http://weblogs.asp.net/scottgu/archive/2007/07/11/linq-to-sql-part-4-updating-our-database.aspx

+0

Ale potrzebny identyfikator który został wygenerowany przy pierwszych przesłanych zmianach, nie wiedział inaczej, jak uzyskać identyfikator. – Drahcir

+3

Odwiedź artykuł napisany przez ScottGu. Możesz powiązać bez ID. To jest piękno LINQ-SQL. Jeśli nie robisz tego w ten sposób, nie wykorzystujesz Linq-To-Sql. Polecam przeczytać artykuł ScottGu. Możesz znaleźć link w mojej odpowiedzi. –

+0

Tak. Wygląda na to, że możesz przepisać to, aby nie wymagać zewnętrznej transakcji. Zaktualizuję moją odpowiedź. – tvanfosson