0

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

使用 SQL Server 2008 在 C# 中进行连接处理的最佳实践是什么?我们有一个调用 SQL Server 的程序集(在我们的例子中由 WCF 服务使用)。一般来说,您似乎需要三个对象来执行此操作:连接对象、命令对象和读取器对象。

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

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

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

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

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

2 回答 2

1

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

对于第 3 点,我相信你可以重新使用 anSqlConnection如果你这样做SqlCommand.ExecuteNonQuery(),但如果你使用 anSqlDataReader你不能重新使用连接 - 它与 绑定SqlDataReader并且必须在完成后关闭/处置。

于 2012-04-20T16:14:27.947 回答
1

除了@PeterMonks 回答:

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

  2. 要连续重复返回数据读取器的命令,您必须 a) 始终在同一线程上执行命令(命令不是线程安全的)和 b)在创建下一个之前Close()或实例。您也可以通过将 DataReaders 放在 using 块中来做到这一点。Dispose()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,但请注意,保持结果集打开会产生开销——您仍然希望在完成阅读器后立即关闭它们,因为未关闭、未处理的阅读器确实代表服务器和客户端上的大量资源分配。

于 2012-04-20T16:24:35.900 回答