C# 中的 SQL Server 2008:连接和命令对象

本文关键字:连接 命令 对象 2008 中的 SQL Server | 更新日期: 2023-09-27 18:31:51

关于这个问题有很多不详细的问题,所以在这里。

使用 SQL Server 2008 在 C# 中进行连接处理的最佳做法是什么?我们有一个程序集(在本例中由 WCF 服务使用),用于调用 SQL Server。通常,似乎需要三个对象才能执行此操作:连接对象、命令对象和读取器对象。

我们能够让呼叫正常工作的唯一可靠方法是执行以下操作:

  1. 打开连接。
  2. 在 using() { } 块中创建命令
  3. 创建读取器以处理响应。
  4. 处理读取器。
  5. 隐式释放 using() 块末尾的命令
  6. 关闭连接。

在多次迭代运行同一命令时,我们遇到了一个不寻常的问题,它会抱怨已经有一个命令或读取器对象附加到仍然打开的连接。唯一坚如磐石的解决方案是关闭并重新打开我们所做的每个命令的连接,迭代或只是顺序(不同的命令)。

所以这就是问题所在,因为我来自数据库连接处理的mysql_pconnect背景。

  1. 打开和关闭每个命令的连接是否会显著影响性能?
  2. 如果是这样,1.,处理串行重复命令的正确解决方法或代码结构是什么?
  3. 有没有办法重用连接、命令或阅读器?
  4. 如果不是 3.,这真的会显着影响性能或内存使用吗(例如,我们的用户会注意到。

C# 中的 SQL Server 2008:连接和命令对象

要回答第 1 点,如果您查看 SqlConnection 的文档,您将看到它对连接池的解释。这意味着 SQL Server 提供程序具有一组随时可用的连接,并且创建的每个SqlConnection只是获取下一个可用连接。因此,为了获得最佳性能,建议继续创建SqlConnection对象并将它们用于短期操作,然后释放它们,从而返回到连接池。

对于第 3 点,我相信如果您这样做SqlCommand.ExecuteNonQuery(),您可以重复使用SqlConnection,但如果您使用SqlDataReader则无法重复使用连接 - 它与SqlDataReader相关联,完成后必须关闭/处置。

除了@PeterMonks答案:

    只要
  1. 使用相同的连接字符串,提供程序(连接池)就会重用 SqlConnection 的"昂贵"非托管部分。 因此,虽然每次创建新的托管包装器都有很小的开销,但它实际上与创建与 SQL Server 实例的连接并不是 1:1 的关系,因此它并不像您想象的那么昂贵。

  2. 要串行重复返回数据读取器的命令,您必须 a) 始终在同一线程上执行命令(命令不是线程安全的)和 b) 在创建下一个实例之前Close()Dispose() DataReader实例。 您也可以通过将 DataReader 放在 using 块中来做到这一点。

以下是将读取器放入使用块的方法:

using (var dr = myCommand.ExecuteReader(...)) {
    // Previous discussions have indicated that a close in here, 
    // while seemingly redundant, can possibly help with the error 
    // you are seeing.
    dr.Close();
}

正如@DavidStratton提到的,另一个有用的技术是启用 MARS,但请注意,保持结果集打开会产生开销 - 您仍然希望在使用完读取器后立即关闭它们,因为未关闭、未处置的读取器确实表示服务器和客户端上的重要资源分配。