2009-04-16 25 views
64

Ho un pezzo di codice che coinvolge più inserti, ma è necessario eseguire il metodo submitchanges prima di terminare l'inserimento in altre tabelle in modo che possa acquisire un ID. Ho cercato su internet e non riuscivo a trovare come creare una transazione in linq a sql. Ho inserito commenti nel codice in cui desidero che la transazione abbia luogo.Come creare una transazione LINQ to 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: Ho dimenticato di dire che è il mio YDC DataContext

risposta

65

Avvolgere il tutto in un TransactionScope. Chiama il numero transaction.Complete() nel punto in cui desideri eseguire il commit. Se il codice esce dal blocco senza chiamare Complete(), la transazione verrà annullata. Tuttavia, dopo aver esaminato la risposta di @ s_ruchit e aver riesaminato il tuo codice, potresti probabilmente riscriverlo per non richiedere uno TransactionScope. Il primo esempio utilizza lo TransactionScope con il tuo codice così com'è. Il secondo esempio apporta alcune modifiche minori, ma ha lo stesso scopo.

Un luogo in cui è necessario utilizzare TransactionScope quando si legge un valore dal database e lo si utilizza per impostare un nuovo valore su un oggetto da aggiungere. In questo caso la transazione LINQ non coprirà la prima lettura, solo la successiva presentazione del nuovo valore. Poiché si sta utilizzando il valore dalla lettura per calcolare un nuovo valore per la scrittura, è necessario che la lettura sia racchiusa nella stessa transazione per garantire che un altro lettore non calcoli lo stesso valore e ovvii alle modifiche. Nel tuo caso stai facendo solo scritture, quindi la transazione LINQ standard dovrebbe funzionare.

Esempio 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; 

Esempio 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

Non sono sicuro sulla sintassi, non ho messo il mio codice in questo ambito: usando (TransactionScope ts = new TransactionScope()) { // il mio codice } – Drahcir

+0

L'ho aggiunto al codice e incollato come esempio. – tvanfosson

+0

Ha funzionato, grazie – Drahcir

38

Non è necessario fare Attuazione transazione esplicita durante l'utilizzo di LINQ to SQL. Tutte le operazioni DB sono incluse in una transazione per impostazione predefinita.

Es:

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(); 

Tutte le operazioni tra db inizializzazione DataContext e db.SubmitChanges() sono avvolti intorno a una transazione di database da Net garantendo il database di essere in costante e con integrità di proprietà mantenuto attraverso le tabelle.

letto un articolo di Scott Guthriehere: - http://weblogs.asp.net/scottgu/archive/2007/07/11/linq-to-sql-part-4-updating-our-database.aspx

+0

ma aveva bisogno di un documento di identità che è stato generato al primo invio delle modifiche, non sapeva altrimenti come acquisire l'id. – Drahcir

+3

Visita l'articolo scritto da ScottGu. È possibile associare senza l'ID. Questa è la bellezza di LINQ-to-SQL. Se non lo fai in questo modo, non stai sfruttando il Linq-to-Sql. Ti consiglio di leggere l'articolo di ScottGu. Puoi trovare il link nella mia risposta. –

+0

Sì. Sembra che potresti riscrivere questo per non richiedere una transazione esterna. Aggiornerò la mia risposta – tvanfosson