What things should I consider when using System.Transactions in my EF project?

1

Background

I have both an MVC app and a windows service that access the same data access library which utilizes EntityFramework. The windows service monitors certain activity on several tables and performs some calculations.

We are using the DAL project against several hundred databases, generating the connection string for the context at runtime.

We have a number of functions (both stored procedures and .NET methods which call on EF entities) which because of the scope of data we are using are VERY db intensive which have the potential to block one another.

The problem

The windows service is not so important that it can't wait. If something must be blocked, the windows service can. Earlier I found a number of SO questions that stated that System.Transactions is the way to go when setting your transaction isolation level to READ UNCOMMITTED to minimize locks.

I tried this, and I may be misunderstanding what is going on, so I need some clarification.

The method in the windows service is structured like so:

private bool _stopMe = false;

public void Update()
{
    EntContext context = new EntContext();
    do
    {
        var transactionOptions = new System.Transactions.TransactionOptions();
        transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;
        using (var transactionScope = new System.Transactions.TransactionScope( System.Transactions.TransactionScopeOption.Required, transactionOptions))
        {
            List<Ent1> myEnts = (from e....Complicated query here).ToList();
            SomeCalculations(myEnts);
            List<Ent2> myOtherEnts = (from e... Complicated query using entities from previous query here).ToList();
            MakeSomeChanges(myOtherEnts);
            context.SaveChanges();
        }
        Thread.Sleep(5000);  //wait 5 seconds before allow do block to continue
    }while (! _stopMe)
}

When I execute my second query, an exception gets thrown:

The underlying provider failed on Open.
    Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please
    enable DTC for network access in the security configuration for MSDTC using the
    Component Services Administrative tool.
        The transaction manager has disabled its support for remote/network
        transactions. (Exception from HRESULT: 0x8004D024)

I can assume that I should not be calling more than one query in that using block? The first query returned just fine. This is being performed on one database at a time (really other instances are being run in different threads and nothing from this thread touches the others).

My question is, is this how it should be used or is there more to this that I should know?

Of Note: This is a monitoring function, so it must be run repeatedly.

entity-framework
transactions
isolation-level
asked on Stack Overflow Jul 18, 2012 by CodeWarrior

1 Answer

1

In your code you are using transaction scope. It looks like the first query uses a light weight db transaction. When the second query comes the transaction scope upgrades the transaction to a distributed transaction.

The distributed transaction uses MSDTC.

Here is where the error comes, by default MSDTC is not enabled. Even if it is enabled and started, it needs to be configured to allow a remote client to create a distributed transaction.

answered on Stack Overflow Sep 12, 2012 by Shiraz Bhaiji

User contributions licensed under CC BY-SA 3.0