Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF: How do I call SaveChanges twice inside a transaction?

Using Entity Framework (code first in my case), I have an operation that requires me to call SaveChanges to update one object in the DB, and then SaveChanges again to update another object. (I need the first SaveChanges to resolve an issue where EF can't figure out which object to update first).

I tried doing:

using (var transaction = new TransactionScope())
{
    // Do something

    db.SaveChanges();

    // Do something else

    db.SaveChanges();

    tramsaction.Complete();
}

When I run that, I get an exception at the second SaveChanges call, saying "the underlying provider failed on open". The inner exception says that MSDTC is not enabled on my machine.

Now, I've seen posts elsewhere that describe how to enable MSDTC, but it seems that I would also need to enable network access, etc. This sounds like complete overkill here, since there are no other databases involved, let alone other servers. I don't want to do something that's going to make my whole application less secure (or slower).

Surely there must be a more lightweight way of doing this (ideally without MSDTC)?!

like image 495
Gary McGill Avatar asked Oct 09 '12 23:10

Gary McGill


People also ask

What's the point of multiple SaveChanges inside an Entity Framework core transaction?

In Entity Framework, the SaveChanges() method internally creates a transaction and wraps all INSERT, UPDATE and DELETE operations under it. Multiple SaveChanges() calls, create separate transactions, perform CRUD operations and then commit each transaction.

What does the Dbcontext SaveChanges () method return?

Returns. The number of state entries written to the underlying database. This can include state entries for entities and/or relationships.

When would you use SaveChanges false AcceptAllChanges ()?

Sometimes though the SaveChanges(false) + AcceptAllChanges() pairing is useful. The most useful place for this is in situations where you want to do a distributed transaction across two different Contexts. If context1. SaveChanges() succeeds but context2.


2 Answers

I know it's kind of late answer but i found it useful to share.

Now in EF6 it's easier to acheeve this by using dbContext.Database.BeginTransaction()

like this :

using (var context = new BloggingContext())
{
    using (var dbContextTransaction = context.Database.BeginTransaction())
    {
        try
        {
            // do your changes
            context.SaveChanges();

            // do another changes
            context.SaveChanges();

            dbContextTransaction.Commit();
        }
        catch (Exception)
        {
            dbContextTransaction.Rollback();
        }
    }
}

for more information look at this

again it's in EF6 Onwards

like image 148
Wahid Bitar Avatar answered Oct 10 '22 23:10

Wahid Bitar


It is probably caused by two different connections used in your transaction. Try to control connection for your operation manually:

var objectContext = ((IObjectContextAdapter)db).ObjectContext;

try {
    //Open Connection
    objectContext.Connection.Open();

    using (var transaction = new TransactionScope()) {
        // Do something

        db.SaveChanges();

        // Do something else

        db.SaveChanges();

        transaction.Complete();
    }
} finally {
    //Close connection after commit
    objectContext.Connection.Close();
} 
like image 21
Ladislav Mrnka Avatar answered Oct 10 '22 21:10

Ladislav Mrnka