2

我有用 C# 编写的命令行实用程序,它更新数据库中的一些记录,然后进入一个循环检查其他一些东西。由于某种原因,SQL 执行总是在 SQL 执行后在 SQL Server 2008 中留下一个休眠的等待命令会话。我可以使用 SQL 服务器活动监视器并运行 sp_who2 来确认这一点。但是SQL事务确实已经提交成功了。我可以从代码中的调试以及数据库中数据记录的时间戳中看出这一点。此外,当我明确停止命令行实用程序时,打开的睡眠会话将被终止。这似乎表明我的函数创建了一些 SQL 连接对象,该对象在应用程序中止时被 CLR 垃圾收集之前无法释放。这怎么可能发生?谢谢。这是代码:

bool result = false;
     using (SqlConnection conn = new SqlConnection(this.Connection))
     {

        using (SqlCommand cmd = conn.CreateCommand())
        {
           cmd.CommandText =
                 @"if not exists (select id from pl where sj=@sj and ej=@ej and dateInactivated is null) 
                       insert into pl(sj,ej,pf, br, tk, lastModified )
                       values(@sj,@ej,@pf,@br,@tk,getDate())
                    else
                       update pl set sj=@sj,ej=@ej,pf=@pf,br=@br,tk=@tk,lastModified=getDate()
                       where sj=@sj and ej=@ej and dateInactivated is null
                    ";

           cmd.Parameters.AddWithValue("@sj", sj);
           cmd.Parameters.AddWithValue("@ej", ej);
           cmd.Parameters.AddWithValue("@pf", pf);
           cmd.Parameters.AddWithValue("@br", br);
           cmd.Parameters.AddWithValue("@tk", tkData);
           cmd.CommandTimeout = 60;
           SqlTransaction trans = null;
           try
           {
              conn.Open();
              trans = conn.BeginTransaction();
              cmd.Transaction = trans;
              cmd.ExecuteNonQuery();
              trans.Commit();
              conn.Close();
              result = true;
           }
           catch (SqlException ex)
           {
              if (trans != null)
              {
                 trans.Rollback();
              }
              Log.WriteLog(LogLevel.ERROR, ex.Message);
              result = false;
           }
           finally
           {
              if (conn.State != ConnectionState.Closed)
              {
                 conn.Close();
              }
           }
        }

     }

     return result;

请注意,tk 字段是一个 xml 数据库字段。

4

2 回答 2

8

这称为连接池,您希望它以这种方式工作

基本上,完全断开连接然后为您的应用程序重新建立连接会比仅重新使用先前调用代码留下的空闲连接产生更高的惩罚。这是一件好事。

于 2012-08-28T17:57:12.490 回答
3

这是由于池化。在 99.99% 的情况下,这是一件好事——它可以减少建立和拆除的连接,如果多线程可以减少同时打开的连接。

如果您添加Pooling=false到连接字符串,它将不会被使用。这样做的唯一原因是:

  1. 作为临时措施,如果您在某处泄漏池连接 - 请注意,就性能而言,这会使糟糕的情况变得更糟,但它不会达到最大池大小。此处重强调。
  2. 您有客户端应用程序共享一个数据库,并在很短的时间内使用连接。在这里,您要关闭池,因为虽然它降低了每个客户端的效率,但它减少了服务器本身的压力。

第二个非常罕见。第一个应该是非常罕见的——再次强调暂时的。

于 2012-08-28T18:07:50.657 回答