我希望在我的.Net应用程序中利用连接池,但对支持准备好的语句和事务有一些担忧。虽然.Net框架似乎提供EnlistTransaction方法来为连接池的事务提供支持,但我试图确定是否存在对预准备语句的类似支持......或者是否需要此类支持。有谁知道这个问题的答案?
答案 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方法并不像我原来希望的那样有用(在我的特定情况下)。由于这个事实,我们似乎必须在我的申请中处理交易作为一个特例。