Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using asynchronous save changes on Entity Framework with multiple contexts

I am using EF 6 with a UoW pattern. I have multiple contexts defined in my UoW since I'm using data from multiple databases. Everything seems to be working correctly except the CommitAsync function I have defined. Here's the code I have:

    public async Task CommitAsync()
    {
        try
        {
            using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            {
                if (_context1 != null)
                    await _context1.SaveChangesAsync();
                if (_context2 != null)
                    await _context2.SaveChangesAsync();

                scope.Complete();
            }
        }
        catch (DbEntityValidationException ex)
        {
            //..
        }
    }

When I run this code saving changes in both contexts I get:

The transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D024)

The await _context2.SaveChangesAsync(); is where the error happens. If I remove the TransactionScope from this function, the code seems to work without error. I am hesitant to remove the scope for multiple contexts.

Just in case it'll help, here's the code I use to call this function:

        state.Name = "Texas";
        _uow.StateRepository.Update(state);

        user.FirstName = "John";
        _uow.UserRepository.Update(user);

        await _uow.CommitAsync();

Thanks!

like image 266
Aaron Sanders Avatar asked Aug 14 '15 14:08

Aaron Sanders


People also ask

Should I use SaveChangesAsync?

But fundamentally, an async call is about much more than that. The idea here is that if there is other work you can do (on the server) while the Save operation is in progress, then you should use SaveChangesAsync . Do not use "await". Just call SaveChangesAsync , and then continue to do other stuff in parallel.

Should I use async with EF core?

The rule of thumb is to use async on any thread that by it's busy type waiting, would hamper other threads. For the use of async will have the operations of waiting to step it aside until the data return.

How do I save changes in Entity Framework?

Entity Framework Core Save Changes to the database using the SaveChanges method of DbContext. When we use the SaveChanges it prepares the corresponding insert , update , delete queries. It then wraps them in a Transaction and sends them to the database. If any of the queries fails all the statements are rolled back.

What does save changes async return?

using of await definitely waits for the method db. SaveChangesAsync() to complete it's execution and it returns a value which shows the affected rows in DB.


1 Answers

Using two connections in the same scope requires MSDTC.

You can enable MSDTC to solve this problem. But it does not work with many HA solutions and is slow.

The only way to avoid using MSDTC is to use the same connection for everything that must be transacted. Since you are using multiple databases that is harder than usual. You need to use SqlConnection.ChangeDatabase or issue the respective SQL to switch between databases on the same connection. The connection must be kept open.

Alternatively, you can use three part names for your object references (e.g. DB1.dbo.MyTable).

There is no other way. Either MSDTC or sharing of the same connection.

like image 168
usr Avatar answered Nov 06 '22 23:11

usr