无法关闭SqlConnection连接

3

我知道这是一个老问题。谷歌上成千上万的语句都说连接会在Dispose()中关闭。然而,谁真正核实了呢?

我发现一个SqlConnection没有任何关闭的方法。我有一个简单的程序(带左侧行号)。

  class Program
  {
    static void Main(string[] args)
1   {
2        var connectionString = "Data Source=localhost;Initial Catalog=master;Integrated Security=SSPI;";
3        using (var conn = new SqlConnection(connectionString))
5        {
6            using (var cmd = new SqlCommand("create table #mytable(col1 int);", conn))
7            {
8                conn.Open();
9                cmd.ExecuteNonQuery();
10           }
11           conn.Close();
12           conn.Dispose();
13       }
14       GC.Collect();
15   }
  }

我有一个T-SQL语句用于检查活动连接。

exec sp_who2

我使用调试器逐行检查程序,同时使用 sp_who2 检查活动连接。
在第11行之后,每个人都期望连接应该被关闭。不是吗?然而,在第11行之后,连接处于 sleep 状态。
好的,尝试在下一行手动处理。但是在第12行之后,连接仍处于 sleep 状态。
好的,下一行是自动处理。但是在第13行之后,连接仍处于 sleep 状态。
好的,这可能与 GC 有关。因此,我明确运行了 GC.Collect() 来尝试收集 conn 对象。但是在第14行之后,连接仍处于 sleep 状态。 实际上,在第15行之后连接已经关闭。这意味着程序结束了。
在上面的程序中,创建了一个临时表 #mytable。但是,只有在连接关闭时才会删除临时表。我们面临的问题是 数据库中存在太多的临时表。(是的,我知道应该在使用后删除临时表。)
我还尝试过:
  1. 使用 { } 创建新范围以包装连接。结果相同。

  2. 创建一个新线程连接到数据库服务器。结果也相同。

  3. Main 方法的结尾使用 while(true) { Thread.Sleep(1000); GC.Collect(); }。结果也相同。

上述任何一种方法都无法关闭 SqlConnection。如何关闭连接呢?
1个回答

9
ADO.NET中的连接池默认启用。这意味着当您“dispose”连接时,您只是将它返回到池中。当您退出程序时,您显然会最终释放池中的所有内容。如果您想避免这种情况,您必须选择退出连接池。
要禁用,请在您的连接字符串中添加“Pooling = false”参数:
var connection = new SqlConnection(
    @"Data Source=(local)\SQLEXPRESS;Initial Catalog=TEST;Integrated " +      
    "Security=SSPI;Pooling=false;");

@quofaye,我很高兴它对你有用。然而,你应该考虑一下是否真的想要禁用连接池。虽然当你完成时看到资源减少肯定是令人满意的,但连接池确实有非常实际的作用。通常,获取新连接是相当昂贵的,而没有池分配一个新连接会产生大量的开销,这些开销在池中完全被消除。 - Kirk Woll
感谢您的评论。是的,在连接池和非连接池之间做出选择确实很难。然而,我只是尝试使用“SqlConnection.ClearPool(conn)”来关闭连接,但是连接仍然在运行中。似乎没有可靠的方法来关闭连接。“Pooling=false”似乎是我这种情况下唯一的选择。 - quofaye
@quofaye,好的 - 如果你确实需要确保在完成后消除连接,那么你可能是正确的,这可能是唯一的选择。 - Kirk Woll
在大多数情况下,您不需要这样做。如果#temp表是问题所在,您应该显式删除临时表,而不是依赖于SQL。 - urlreader

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接