TransactionScope Prematurely Completed

泪湿孤枕 提交于 2019-11-28 16:56:55

Don't forget to supress your select statements from your TransactionScope. In SQL Server 2005 and above, even when you use with(nolock), locks are still created on those tables the select touches. Check this out, it shows you how to setup and use TransactionScope.

using(TransactionScope ts = new TransactionScope 
{ 
  // db calls here are in the transaction 
  using(TransactionScope tsSuppressed = new TransactionScope (TransactionScopeOption.Suppress)) 
  { 
    // all db calls here are now not in the transaction 
  } 
} 

I've found that this message can occur when a transaction runs for a longer period than the maxTimeout for System.Transactions. It doesn't matter that TransactionOptions.Timeout is increased, it can't exceed maxTimeout.

The default value of maxTimeout is set to 10 minutes and its value can only be modified in the machine.config

Add the following (in the configuration level) to the machine.config to modify the timeout:

<configuration>
    <system.transactions>
        <machineSettings maxTimeout="00:30:00" />
    </system.transactions>
</configuration>

The machine.config can be found at: %windir%\Microsoft.NET\Framework\[version]\config\machine.config

You can read more about it in this blog post: http://thecodesaysitall.blogspot.se/2012/04/long-running-systemtransactions.html

Rolf

I can reproduce the problem. It is a transaction timeout.

using (new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 0, 1)))
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        using (var sqlCommand = connection.CreateCommand())
        {
            for (int i = 0; i < 10000; i++)
            {
                sqlCommand.CommandText = "select * from actor";
                using (var sqlDataReader = sqlCommand.ExecuteReader())
                {
                    while (sqlDataReader.Read())
                    {
                    }
                }
            }
        }
    }
}

Throws System.InvalidOperationException with this message:

The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute SQL statements.

To solve the problem make your query run faster or increase the timeout.

If an exception happens inside a TransactionScope it is rolled back. This means that TransactionScope is done. You must now call dispose() on it and start a new transaction. I'm honestly not sure if you can reuse the old TransactionScope or not, I've never tried, but I'd assume not.

My issue was a stupid one, if you sit on a debug break through the timeout you will get this. Face Palm

Man, programming makes you feel thick some days...

Confirmed this error can also be caused by a transaction timeout. Just to add to what Marcus + Rolf have stated, if you haven't explicitly set a timeout on the TransactionScope, the timeout TimeSpan will assume a default value. This default value is the smaller of:

  1. If you've overridden the local app.config / web.config setting, e.g.

    <system.transactions>
    <defaultSettings timeout="00:05:00" />
    </system.transactions>
    
  2. But this is then 'capped' at the machine.config setting <machineSettings maxTimeout="00:10:00" />

Adrian Tarnowski

This exception can also be caused by disable Microsoft Distributed Transaction Coordinator.

If we want enable it, we run "dcomcnfg" and select "Component Services" -> "My Computer" -> "Distributed Transaction Coordinator" -> "Local Service DTC" and choose "Properties".

It should be checked "Allow Remote Client", "Allow Inbound", "Allow Outbound" and "No Authentication Required".

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!