【问题标题】:Intermittent Error while using multiple readers使用多个阅读器时出现间歇性错误
【发布时间】:2013-12-12 14:53:28
【问题描述】:

以下是来自SqlDataReader Class的声明

在使用 SqlDataReader 时,关联的 SqlConnection 正忙于为 SqlDataReader 服务,除了关闭 SqlConnection 之外,不能对它执行其他操作。

我的代码有一个打开的连接被两个不同的命令使用。其实有两种方法。第二种方法在while(reader.Read()) 循环中被调用。

我收到 间歇性 错误提示 - There is already an open DataReader associated with this Command which must be closed first

但为什么它不总是抛出错误?

参考文献

  1. Default Result Set Processing and Multiple Active Result Sets
  2. SQL Server Connection Basics
  3. Regarding a small confusion about DataReader

【问题讨论】:

  • 显示这些方法和相关代码。我认为这是一种竞争条件。但是为什么你使用相同的连接?在这两种方法中都使用using-statement。
  • ResultRead 区域也不错:)
  • @Lijo:不要发布图片,而是发布文字。目前尚不清楚ResultRead 的含义是什么,如果它是显示所有参数的方法。您还显示了一个类DataAccessLayerBase,它没有在上面的代码中使用。
  • 我相当肯定你最好废弃你的DataAccessLayerBase-class。你是poaching on the Connection-Pool's territory吗?
  • 尝试在仍在返回数据的连接上执行命令是自找麻烦,即使它被允许。只是不要使用相同的连接。反复打开和关闭一个连接不会产生任何费用——连接池会注意重用以前关闭的连接。实际上,使用池要快得多,因为更少的连接意味着更少的锁定资源

标签: c# ado.net sqldatareader


【解决方案1】:

既然您知道在同一连接上嵌套数据读取器是一个坏主意,您为什么还要这样做?重构该代码。

现在回答你的问题,

网络层在 PULL 模式下不起作用。您打开一个连接,发出一些命令,然后开始使用结果。请注意,您不是 pull,而是 consume。它们是有区别的。在您的代码中,while(reader.Read) 循环不会稳定地提取数据。数据在命令执行的那一刻开始到达。它会在您的电脑上缓冲。缓冲区有限制。如果总数据小于缓冲区大小,则数据传输发生得非常快。如果总数据大于缓冲区大小,那么reader.read() 当然会为下一批腾出空间。

这意味着两个DataReaders 可以与相同的connection 一起工作,只要第一个数据读取器获取的数据量很少。因此,当第二个数据读取器尝试使用该连接时,该连接已经空闲。

两个线程之间存在竞争条件。第一个线程是收集响应第一个命令而发送的数据的线程。第二个线程是您的程序正在运行的线程。双方比赛都先完成。如果收集器线程能够在您的主线程命中第二个数据读取器之前下载所有数据,则可以避免事故。但是如果数据很大或者网络很慢,或者只是运气好没有得到足够的cpu,那么主线程会在连接仍然工作时访问第二个数据读取器。

【讨论】:

  • 我不知道你为什么认为这里涉及到两个线程。
  • @Joe:只有一个线程:程序主线程。还有其他线程,即执行网络活动的框架线程。它们是隐藏的,您只能看到它们的名称和 ID。
猜你喜欢
  • 2022-06-16
  • 2021-05-16
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 2017-07-22
  • 2023-03-11
  • 1970-01-01
  • 2015-07-19
相关资源
最近更新 更多