3

I'm trying to understand transactions in entity framework 6.. I searched a lot but I'm still confused..

Take a look at this:

Dim transaction = context.Database.BeginTransaction()

Using transaction 
.
.
context.Entry(entity1).State = System.Data.EntityState.Added;
SaveChanges()
.
.
context.Entry(entity2).State = System.Data.EntityState.Added;
SaveChanges()
.
.
context.Entry(entity3).State = System.Data.EntityState.Added;
SaveChanges()

Transaction.Commit()
'Or Transaction.RollBack()
End using

Now what exactly does SaveChanges() Do? and how does it differ from the commit??

Does it begin a new (maybe internal) transaction for each insert and then commit it?

I read https://msdn.microsoft.com/en-us/data/dn456843.aspx.

..that was what I understood from "In all versions of Entity Framework, whenever you execute SaveChanges() to insert, update or delete on the database the framework will wrap that operation in a transaction. This transaction lasts only long enough to execute the operation and then completes. When you execute another such operation a new transaction is started."

geothachankary
  • 1,040
  • 1
  • 17
  • 30
Abeer Sul
  • 944
  • 9
  • 22

1 Answers1

3

My understanding is, all changes to the entities (especially where there are relationships that have cascaded deletes, or, reinsert an item that has been deleted) is to sort the operations so they are carried out in the correct order.

For example, if you have a table with a unique constraint, and you have deleted one entity with a unique value on the column with the constraint and reinserted another entity with the same value, the operations are carried out in the correct order so the underlying dmbs doesn't throw a unique constraint exception. The goes for non auto incremented primary keys and a variety of other things although hopefully you get the gist of it.

The entities are stored in a graph with the relationships as edges so it can sort the graph and perform the operations in the correct order.

This is carried out by the ChangeTracker. I know this from working with / building my own entity tracker using the source code from the awesome IQToolkit.

I also understand that this is carried out in a single transaction, if the underlying dmbs supports it...

Also, in your example, you only need to call

SaveChanges()

Once not after each time you change an entity.

You also don't need to create an explicit transaction and commit it, as SaveChanges does this internally, unless you need to rollback the transaction due to some external factor

EDIT

To explicitly answer your questions in bold:

"Now what exactly does SaveChanges() Do? and how does it differ from the commit??"

It sorts the sql commands generated by each change made to the entities and executes them, in a single transaction, in an order that will not violate any relationship or field constraints setup within the database. As it uses its own transaction, you don't need to wrap the operation in a new transaction and commit it, unless you have a reason to roll the operations back due to some external factor.

It differs from Commit as Commit will commit any changes made during a transaction, while SaveChanges creates it's own transaction around the updates and commits the transaction. What you are doing is nesting the transaction created by SaveChanges in the outer transaction, so you can cancel it if required.

"Does it begin a new (maybe internal) transaction for each insert and then commit it?"

No, it wraps them all and commits in a single, internal transaction.

Jack
  • 425
  • 4
  • 12
  • to be more precise: SaveChanges() will only wrap its computed sql queries in a new transaction if there is no ambient transaction, as seen in the example. so in this context (what was given in the example by OP) the last SaveChanges will overwrite all previous ones because all are wrapped in one transaction and will compute the sql queries necessary to save the changes in the context onto the database, to then be rolled out upon Transaction.Commit(). One more thing to note on this regard: its better to use BeginTransaction() in a using statement so you don't have to dispose it yourself (to OP) – DevilSuichiro Jan 11 '16 at 11:52
  • can I use commit and omit SaveChanges? I've tested and the changes are saved in the db – Toolkit Dec 30 '18 at 12:51