Oct 302008
 

Don’t be so quick to blame the service or MSDTC when you see the error “Communication with the underlying transaction manager has failed.”

Symptom:

An error message that reads something like:

System.Transactions.TransactionManagerCommunicationException: Communication with the underlying transaction manager has failed. —> System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component.

Solutions:

 

“Check your firewall settings” is what you will find in almost all forum posts and on MSDN. You need port 135 open bi-directionally for RPC’s end point mapper (EPM). You also need ports 1024-5000 open bi-directionally if you have not specified your own port settings for RPC in the registry. If you have your own ports specified in the registry, then those need to be open bi-directionally.

 

WHAT ?!? It may also be your code causing the issue. If you are using TransactionScope, you have to be mindful of every method called within the using braces. Looking at the code below, you will see two service calls and a seemingly innocuous ShouldContinue() method checking to see if the second operation should be called.

using (TransactionScope scope = new TransactionScope())

using (MyServiceClient proxy = new MyServiceClient())

{

       proxy.DoOperationOne(someID);

      

       if (ShouldContinue()) // uh, oh! What if this has an ADO.NET connection that is opened and closed inside it?

       {

               proxy.DoOperationTwo(someOtherID);

       }

}

If ShouldContinue() opens and closes an SqlConnection, the TransactionScope object has no means by which to commit or rollback this part of the transaction. This will cause the error “Communication with the underlying transaction manager has failed.”

 

1. If you do not need to results of DoOperationOne() to feed ShouldContinue(), then do that logic before the TransactionScope using block.

2. If you do need the result of DoOperationOne() to feed ShouldContinue(), then you can wrap the internals of ShouldContinue() with a TransactionScope using block specifying TransactionScopeOption.Suppress. This will not add the resource access contained within the block to the ambient transaction.

3. Use an intelligent data access library like Enterprise Library that manages your connections for you. It won’t close the connection if enlisted in a transaction.

 

Look at your code before you involve your network dudes. This is more common when integrating legacy code with new service calls.

 Posted by at 2:54 am

  2 Responses to “Communication with the underlying transaction manager has failed.”

  1. Scott,

    Thanks for writing this blog entry. I’ve been getting the error "Communication with the underlying transaction manager has failed" intermittently. I can’t identify the event that causes it start happening, but I am able to temporarily resolve it by rebooting my development machine. After that I’m usually good for several hours. Everything I’ve read online up this point indicated that it was some type of network issue. But I’m not sure my particular issue is strictly a network issue. Some of the suggestion in your blog have given me new avenues to look into.

    "If ShouldContinue() opens and closes an SqlConnection, the TransactionScope object has no means by which to commit or rollback this part of the transaction. This will cause the error ‘Communication with the underlying transaction manager has failed.’"

    I definitely have code that opens and closes a SqlConnection within a using TransactionScope block. However, what I find confusing is that my code works fine for several hours before I get this error. Do you have any ideas why this could be?

    I’m developing an asp.net web application in vs 2005 on an xp pro sp2 machine which . The database (sql server 2005) is on a Win 2003 server. In this scenario, I’m assuming that my dev machine is the dtc client and the db server is the dtc server, but I don’t really understand how the client (my dev machine) determines where the server is.

    Thanks again for your post.

    Mike

  2. "If ShouldContinue() opens and closes an SqlConnection, the TransactionScope object has no means by which to commit or rollback this part of the transaction."

    I’m not sure what you mean. While I do not know the details of what the DTC is doing, it does manage statements from opened and then closed connections. In the TransactionScope example from Visual Studio Help, both connection1 and connection2 are disposed (and therefore closed) within the transaction scope:

    using (TransactionScope scope = new TransactionScope())
    {
    using (SqlConnection connection1 = new SqlConnection(connectString1))
    {
    connection1.Open();
    returnValue = command1.ExecuteNonQuery();
    using (SqlConnection connection2 = new SqlConnection(connectString2))
    {
    connection2.Open();
    returnValue = command2.ExecuteNonQuery();
    }
    }
    scope.Complete();
    }

    Could you please clarify your comments? We have seen this error intermittently in bunches (5 in a minute, 5 times per month) during one of our transaction steps, the one to .Net Membership CreateUser() – which manages its own connection. So perhaps this is related to what you are stating?

    Thank you,
    Dan

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)