带有准备语句和事务的SQL Server连接池

时间:2015-02-25 16:41:33

标签: c# .net transactions sql-server-2012 prepared-statement

我希望在我的.Net应用程序中利用连接池,但对支持准备好的语句和事务有一些担忧。虽然.Net框架似乎提供EnlistTransaction方法来为连接池的事务提供支持,但我试图确定是否存在对预准备语句的类似支持......或者是否需要此类支持。有谁知道这个问题的答案?

1 个答案:

答案 0 :(得分:0)

TL; DR - .Net SQL Server连接池无缝处理预准备语句。

我创建了一个主程序来测试这个......

private static void TestPreparedStatement()
{
    const string sql = "INSERT INTO myTable(id, numInt) " +
                       "VALUES((SELECT MAX(id) " +
                               "FROM myTable) + 1, @numInt);";
    using (SqlConnection dbConn = new SqlConnection(s_connStr))
    {
        dbConn.Open();
        Console.WriteLine("Getting ready to prepare statement on connection with ID " + dbConn.ClientConnectionId);
        s_cmd = new SqlCommand(sql, dbConn);
        s_cmd.Parameters.Add("@numInt", SqlDbType.Int);
        s_cmd.Prepare();
        Console.WriteLine("The command has been prepared.");
    }

    for (int threadNdx = 0; threadNdx < 10; ++threadNdx)
    {
        Thread prepStmntThread = new Thread(ExecPrepStmnt)
        {
            Name = threadNdx.ToString()
        };

        prepStmntThread.Start();
    }
}

private static void ExecPrepStmnt()
{
    using (SqlConnection dbConn = new SqlConnection(s_connStr))
    {
        dbConn.Open();
        lock (s_cmd)
        {
            Console.WriteLine("Thread #" + Thread.CurrentThread.Name + " has ownership of the command.");
            s_cmd.Connection = dbConn;
            s_cmd.Parameters["@numInt"].Value = int.Parse(Thread.CurrentThread.Name);
            Console.WriteLine("Thread #" + Thread.CurrentThread.Name + " is about to execute the command on the connection with ID " + s_cmd.Connection.ClientConnectionId + ".");
            try
            {
                s_cmd.ExecuteNonQuery();
                Console.WriteLine("Thread #" + Thread.CurrentThread.Name + " successfully executed the command.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Thread #" + Thread.CurrentThread.Name + " failed to execute the command.");
                Console.WriteLine(e.Message);
            }

            Console.WriteLine("Thread #" + Thread.CurrentThread.Name + " is about to relinquish ownership of the command.");
        }

        Console.WriteLine("Thread #" + Thread.CurrentThread.Name + " is going to sleep with open pooled connection.");
        Thread.Sleep(5 * 1000);
    }

    Console.WriteLine("Thread #" + Thread.CurrentThread.Name + " has woken up and disposed of its pooled connection.");
}

输出是......

Getting ready to prepare statement on connection with ID 289ae798-7564-4b7c-b45f-60d09d54fa87
The command has been prepared.
Thread #0 has ownership of the command.
Thread #0 is about to execute the command on the connection with ID 289ae798-7564-4b7c-b45f-60d09d54fa87.
Thread #0 successfully executed the command.
Thread #0 is about to relinquish ownership of the command.
Thread #0 is going to sleep with open pooled connection.
Thread #2 has ownership of the command.
Thread #2 is about to execute the command on the connection with ID 2585e1fb-980a-45ee-9a59-17d94f44b2d5.
Thread #2 successfully executed the command.
Thread #2 is about to relinquish ownership of the command.
Thread #2 is going to sleep with open pooled connection.
Thread #1 has ownership of the command.
Thread #1 is about to execute the command on the connection with ID 2772d6a2-dc23-472d-bb4e-adfa99e97bdf.
Thread #1 successfully executed the command.
Thread #1 is about to relinquish ownership of the command.
Thread #1 is going to sleep with open pooled connection.
Thread #3 has ownership of the command.
Thread #3 is about to execute the command on the connection with ID 1ce7f447-f485-4b85-9ede-2854fc160a83.
Thread #3 successfully executed the command.
Thread #3 is about to relinquish ownership of the command.
Thread #3 is going to sleep with open pooled connection.
Thread #4 has ownership of the command.
Thread #4 is about to execute the command on the connection with ID 62d62a9c-b2e0-42e5-99da-3682cf7614ee.
Thread #4 successfully executed the command.
Thread #4 is about to relinquish ownership of the command.
Thread #4 is going to sleep with open pooled connection.
Thread #5 has ownership of the command.
Thread #5 is about to execute the command on the connection with ID cb62e434-534a-49a7-afbd-96e85f7e5888.
Thread #5 successfully executed the command.
Thread #5 is about to relinquish ownership of the command.
Thread #5 is going to sleep with open pooled connection.
Thread #6 has ownership of the command.
Thread #6 is about to execute the command on the connection with ID 946ccf21-a278-46ad-871f-5030ee00fcd0.
Thread #6 successfully executed the command.
Thread #6 is about to relinquish ownership of the command.
Thread #6 is going to sleep with open pooled connection.
Thread #7 has ownership of the command.
Thread #7 is about to execute the command on the connection with ID a4b36316-8f82-44ff-998b-f33b94b34320.
Thread #7 successfully executed the command.
Thread #7 is about to relinquish ownership of the command.
Thread #7 is going to sleep with open pooled connection.
Thread #8 has ownership of the command.
Thread #8 is about to execute the command on the connection with ID 11f558a0-128d-4401-94cb-57fff007ae81.
Thread #8 successfully executed the command.
Thread #8 is about to relinquish ownership of the command.
Thread #8 is going to sleep with open pooled connection.
Thread #9 has ownership of the command.
Thread #9 is about to execute the command on the connection with ID c613e347-1471-4476-a6d7-1485e2c731c5.
Thread #9 successfully executed the command.
Thread #9 is about to relinquish ownership of the command.
Thread #9 is going to sleep with open pooled connection.
Thread #0 has woken up and disposed of its pooled connection.
Thread #2 has woken up and disposed of its pooled connection.
Thread #1 has woken up and disposed of its pooled connection.
Thread #3 has woken up and disposed of its pooled connection.
Thread #4 has woken up and disposed of its pooled connection.
Thread #5 has woken up and disposed of its pooled connection.
Thread #6 has woken up and disposed of its pooled connection.
Thread #7 has woken up and disposed of its pooled connection.
Thread #8 has woken up and disposed of its pooled connection.
Thread #9 has woken up and disposed of its pooled connection.

所以基本上看起来根本没有什么可担心的。当我运行上面的测试程序时,我的老板在数据库服务器上运行了一个SQL Server配置文件,并声称他从未真正看到过对sp_prepare的调用。考虑到SQL Server缓存执行计划这一事实,这可能不是什么大问题。

不幸的是,自从编写我的问题以来,我意识到SqlConnection.EnlistTransaction方法并不像我原来希望的那样有用(在我的特定情况下)。由于这个事实,我们似乎必须在我的申请中处理交易作为一个特例。