Я чувствую, что такого поведения не должно происходить. Здесь сценарий:
-  
Запустите долгосрочную транзакцию sql.
 -  
Поток, который запускал команду sql (не по нашему коду!)
 -  
Когда поток возвращается к управляемому кода, состояние SqlConnection "Закрыто", но транзакция все еще открыт на сервере sql.
 -  
SQLConnection можно повторно открыть, и вы можете попытаться вызвать откат на транзакции, но у нее нет (не то, что я ожидал бы такого поведения. Дело в том, что нет способа получить доступ к транзакции на db и отбросить ее.)
 
Проблема заключается в том, что транзакция не очищается должным образом, когда поток прерывается. Это была проблема с .Net 1.1, 2.0 и 2.0 SP1. Мы запускаем .Net 3.5 SP1.
Вот пример программы, которая иллюстрирует проблему.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Threading;
namespace ConsoleApplication1
{
    class Run
    {
        static Thread transactionThread;
        public class ConnectionHolder : IDisposable
        {
            public void Dispose()
            {
            }
            public void executeLongTransaction()
            {
                Console.WriteLine("Starting a long running transaction.");
                using (SqlConnection _con = new SqlConnection("Data Source=<YourServer>;Initial Catalog=<YourDB>;Integrated Security=True;Persist Security Info=False;Max Pool Size=200;MultipleActiveResultSets=True;Connect Timeout=30;Application Name=ConsoleApplication1.vshost"))
                {
                    try
                    {
                        SqlTransaction trans = null;
                        trans = _con.BeginTransaction();
                        SqlCommand cmd = new SqlCommand("update <YourTable> set Name = 'XXX' where ID = @0; waitfor delay '00:00:05'", _con, trans);
                        cmd.Parameters.Add(new SqlParameter("0", 340));
                        cmd.ExecuteNonQuery();
                        cmd.Transaction.Commit();
                        Console.WriteLine("Finished the long running transaction.");
                    }
                    catch (ThreadAbortException tae)
                    {
                        Console.WriteLine("Thread - caught ThreadAbortException in executeLongTransaction - resetting.");
                        Console.WriteLine("Exception message: {0}", tae.Message);
                    }
                }
            }
        }
        static void killTransactionThread()
        {
            Thread.Sleep(2 * 1000);
            // We're not doing this anywhere in our real code.  This is for simulation
            // purposes only!
            transactionThread.Abort();
            Console.WriteLine("Killing the transaction thread...");
        }
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            using (var connectionHolder = new ConnectionHolder())
            {
                transactionThread = new Thread(connectionHolder.executeLongTransaction);
                transactionThread.Start();
                new Thread(killTransactionThread).Start();
                transactionThread.Join();
                Console.WriteLine("The transaction thread has died.  Please run 'select * from sysprocesses where open_tran > 0' now while this window remains open. \n\n");
                Console.Read();
            }
        }
    }
}
Существует исправление Microsoft, нацеленное на .Net2.0 SP1, который должен был решить эту проблему, но мы, очевидно, имеем более новую DLL (.Net 3.5 SP1), которые не соответствуют номерам версий, указанным в этом исправлении.
Может ли кто-нибудь объяснить это поведение и почему ThreadAbort все еще не очищает транзакцию SQL? Does.Net 3.5 SP1 не включает это исправление или это технически корректно?