ADO.Net:重用打开的 SqlConnection 还是每次都获取一个新的?

A-K*_*A-K 5 ado.net sql-server-2008 sql-server-2008-r2 c#-4.0

在发布这个问题之前,我已经在这个网站上阅读了几个答案:like thisthis。每个人似乎都同意“c# 应用程序池针对对同一数据库的多次调用进行了优化”。

但是,如果我从池中获得连接,我仍然观察到显着的性能损失。这是我的基准:

    private const string localConnString = "Data Source=(local);Integrated Security=SSPI;database=MyTest;Pooling=true";


    [Test]
    public void GetNewConnectionEveryTime()
    {
        var stopwatch = new Stopwatch();
        stopwatch.Start();
        for (var i = 0; i < 1000; i++)
        {
            using (var conn = new SqlConnection(localConnString))
            {
                conn.Open();
                const string saveTrancount = "EXEC dbo.TestTran";
                ExecuteSql(conn, saveTrancount);
            }
        }
        stopwatch.Stop();
        Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
        //Time elapsed: 00:00:00.5576016
    }

    [Test]
    public void ReuseOneConnection()
    {
        var stopwatch = new Stopwatch();
        stopwatch.Start();
        using (var conn = new SqlConnection(localConnString))
        {
            conn.Open();
            for (var i = 0; i < 1000; i++)
            {
                const string saveTrancount = "EXEC dbo.TestTran";
                ExecuteSql(conn, saveTrancount);
            }
        }
        stopwatch.Stop();
        Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
        //Time elapsed: 00:00:00.1110324
    }

    private void ExecuteSql(SqlConnection conn, string sql, int timeout = 0)
    {
        var command = conn.CreateCommand();
        command.CommandText = sql;
        command.CommandType = CommandType.Text;
        command.CommandTimeout = timeout;
        command.ExecuteNonQuery();
    }
Run Code Online (Sandbox Code Playgroud)

显然,从池中获取连接所需的时间(00:00:00.5576016 - 00:00:00.1110324 appr 0.44)是实际工作(第二个基准测试中的 00:00:00.1110324)的四倍。我错过了什么?

编辑:我正在针对在 RAM 磁盘上创建的数据库运行这些基准测试,因此我所有的数据库操作都非常快。

spa*_*dba 4

你的基准对我来说很有意义。如果您在每次迭代时打开和关闭连接而不使用连接池,情况会更糟,但这是一个完全不同的故事。但是,当您关闭池连接时,您会将其返回到池中:在幕后,SNAC 发出 sp_reset_connection 并将连接放回到池中。通常,这是一个非常快的操作(除非阻塞开始),但它必须花费一些虽小但非零的时间。
重复使用相同的连接,而无需在每次迭代中关闭和打开,可以避免这种小滞后。
但是,如果您比较池化连接和非池化连接的相同使用,那么对我来说会更有意义。你尝试过吗?

这是关于 sp_reset_connection 的有趣帖子