【问题标题】:SQL Server 2008 in C#: Connections and Command ObjectsC# 中的 SQL Server 2008:连接和命令对象
【发布时间】:2012-05-02 05:42:12
【问题描述】:

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

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

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

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

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

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

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

【问题讨论】:

标签: c# performance sql-server-2008 reusability


【解决方案1】:

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

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

【讨论】:

  • 我把它然后DataReader本身绑定到命令,此时不能改变?
【解决方案2】:

除了@PeterMonks 的回答:

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

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

以下是将阅读器放入 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,但请注意,保持结果集打开会产生开销——你仍然希望在完成阅读器后立即关闭它们,因为未关闭、未处理reader 确实代表了服务器和客户端上的重要资源分配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多