7

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!

11
  • 1
    There's nothing wrong with the code it is the config on the box running the code msdtc has got remote/network transactions disabled. Commented Aug 14, 2015 at 14:32
  • Why do you want to use the TransactionScope? If the save fails it will be undone anyway. Using TransactionScope just leads to possible deadlocks. Commented Aug 14, 2015 at 14:32
  • 2
    @JamieRees I suspect the OP wants either both updates to work or both to fail and avoid a situation where one worked but one failed. Commented Aug 14, 2015 at 14:34
  • Yeah that would make sense! Commented Aug 14, 2015 at 14:34
  • 2
    Are you aware that this requires distributed transactions? Main problem is that they do not work with many HA solutions. Problem 2 is performance. Commented Aug 14, 2015 at 14:37

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

5 Comments

thank you for your help. I suppose another option is just to remove the scope, but be left with the possibility of the above posted by Ben. I suppose that wouldn't be terrible in my situation since the data being saved in the different databases isn't really related.
@AaronSanders if you like debugging inconsistent data... This will happen. Timeout can happen at any time.
@AaronSanders additional reading for you "Two Generals Problem". This is the thought experiment that describes how FRIGGIN hard distributed transactions are.
@Aron good point, and most people don't know that it's impossible to have 100% reliable distributed transactions. Strangely, this is never mentioned in the product documentations...
@usr I assume that most people expect software to obey to laws of mathematics/physics.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.