使用嵌套命令时可以避免打开 DataReader 异常吗?
Posted
技术标签:
【中文标题】使用嵌套命令时可以避免打开 DataReader 异常吗?【英文标题】:Can I avoid the open DataReader exception when using nested commands? 【发布时间】:2009-09-01 11:39:28 【问题描述】:在使用类似这样的构造时,我能否避免打开 DataReader 异常(“已经有一个打开的 DataReader 与此命令关联,必须先关闭。”)?
public void FirstMethod()
using (var command = connection.CreateCommand())
command.CommandText = "...";
using (var reader = command.ExecuteReader())
// do something with the data
SecondMethod();
public void SecondMethod()
using (var command = connection.CreateCommand())
command.CommandText = "...";
using (var reader = command.ExecuteReader()) // Exception
最好的问候
【问题讨论】:
【参考方案1】:您可以使用本地连接(即方法的本地连接);使用连接池,将连接保留为字段的优势是微乎其微的,并且经常会引起这种类型的……乐趣。当然,如果您正在编辑数据,您可能会遇到阻止自己的问题——也许使用TransactionScope
之类的东西可以缓解。底部示例...
或者,您可以在连接上启用 MARS(多个活动结果集);应该这样做。只需在连接字符串中包含“MultipleActiveResultSets=True”作为一对(SQL Server 2005 及更高版本)。
public void FirstMethod()
using (var connection = CreateAndOpenConnection())
using (var command = connection.CreateCommand())
command.CommandText = "...";
using (var reader = command.ExecuteReader())
// do something with the data
SecondMethod();
public void SecondMethod()
using (var connection = CreateAndOpenConnection())
using (var command = connection.CreateCommand())
command.CommandText = "...";
using (var reader = command.ExecuteReader()) // Exception
private SqlConnection CreateAndOpenConnection()
var conn = new SqlConnection(connectionString);
conn.Open(); // perhaps dispose if this fails...
return conn;
【讨论】:
【参考方案2】:为什么不直接更改方法签名?
public void FirstMethod()
using (var command = connection.CreateCommand())
command.CommandText = "...";
using (var reader = command.ExecuteReader())
// do something with the data
SecondMethod(reader);
public void SecondMethod(var reader)
// do stuff with reader...
这不仅避免了这个问题,而且还产生了更少的开销,因为您只创建了 1 个 command
/reader
而不是 2 个。(这假设您的方法调用是同步的。)
另外,考虑使用强类型变量而不是var
关键字;引入var
是为了支持匿名类型,并且只应在必要时使用。
【讨论】:
好吧,如果第二种方法基于相同的 sql 语句,我会这样做,当然不是这样(否则,我为什么需要方法?)。 @Ian:所有变量在 C# 中都是强类型的,但是你声明它们。 (C#4 发布时将允许使用dynamic
变量,但它们与 var
关键字无关。)
是的,var 关键字只是隐藏了具体类型,但隐含地表示了它。所以你可以写“int i = 1”和“var i = 1”,两个语句是相等的。
阅读器不是“只进”吗?因此,您将无法 // 用阅读器做事...
@AMissico:DataReader
可能包含多个结果集。见NextResult
方法:msdn.microsoft.com/en-us/library/…以上是关于使用嵌套命令时可以避免打开 DataReader 异常吗?的主要内容,如果未能解决你的问题,请参考以下文章
调用另一个 repo 时出错 - '已经有一个打开的 DataReader 与此命令关联,必须先关闭'
实体框架运行时错误 - 已经有一个打开的 DataReader 与此命令关联,必须先关闭
尝试插入、更新或删除时出错:已经有一个打开的 DataReader 与此命令关联,必须先关闭
EF6 - 已经有一个打开的 DataReader 与此命令关联,必须先关闭