I have a piece of code that involves multiple inserts but need to execute submitchanges method before I finish inserting in other tables so that I can aquire an Id. I have been searching through the internet and couldnt find how to create a transaction in linq to sql. I have put comments in the code where I want the transaction to take place.
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: Forgot to mention that ydc is my datacontext
LINQ to SQL translates the queries you write into equivalent SQL queries and sends them to the server for processing. More specifically, your application uses the LINQ to SQL API to request query execution. The LINQ to SQL provider then transforms the query into SQL text and delegates execution to the ADO provider.
LINQ to SQL was the first object-relational mapping technology released by Microsoft. It works well in basic scenarios and continues to be supported in Visual Studio, but it's no longer under active development.
In LINQ to SQL, the data model of a relational database is mapped to an object model expressed in the programming language of the developer. When the application runs, LINQ to SQL translates into SQL the language-integrated queries in the object model and sends them to the database for execution.
Wrap the whole thing in a TransactionScope
. Call transaction.Complete()
at the point where you want to commit. If the code exits the block without Complete()
being called, the transaction will be rolled back. However, after looking at @s_ruchit's answer and re-examining your code, you could probably rewrite this to not require a TransactionScope
. The first example uses the TransactionScope
with your code as is. The second example makes some minor changes, but accomplishes the same purpose.
A place where you would need to use the TransactionScope
is when you are reading a value from the database and using it to set a new value on an object being added. In this case the LINQ transaction won't cover the first read, just the later submit of the new value. Since you are using the value from the read to calculate a new value for the write, you need the read to be wrapped in the same transaction to ensure that another reader doesn't calculate the same value and obviate your change. In your case you are only doing writes so the standard LINQ transaction should work.
Example 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;
Example 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; }
You do not need to do explicit Transaction Implementation while using LINQ to SQL. All DB operations are wrapped in a transaction by default.
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();
All operations between db DataContext initialization and db.SubmitChanges() are wrapped around a Database Transaction by .Net ensuring your database to be in consistent and with property integrity maintained across tables.
Read an article By Scott Guthrie here :- http://weblogs.asp.net/scottgu/archive/2007/07/11/linq-to-sql-part-4-updating-our-database.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With