我有2个SqlCommand,其中一个是嵌套的。为什么它不允许我发出第二个SqlCommand(我使用单独的SQLCommand)?它给出了错误"已经有一个与此命令关联的开放DataReader必须先关闭。" 。如果我使用单独的SqlConnection,那很好。
SqlCommand cmd = new SqlCommand(qry, cn);
SqlDataReader rd = cmd.ExecuteReader();
while (rd.Read())
{
....
try
{
SqlCommand cmd2 = new SqlCommand(qry2, cn);
cmd2.ExecuteNonQuery();
}
catch (Exception e)
{
// I get this error here
// System.Data; There is already an open DataReader associated with this Command which must be closed first.
}
}
答案 0 :(得分:1)
消息很明显:在SqlCommand
仍处于打开状态时,您无法同时为不同的DataReader
实例使用相同的连接。 SqlDataReader
实例解释已经说过:
在使用SqlDataReader时,关联的SqlConnection是 忙于服务SqlDataReader,没有其他操作可以 在SqlConnection上执行而不是关闭它。情况就是这样 直到调用SqlDataReader的Close方法。例如, 在调用Close之前,您无法检索输出参数。
此问题的常见解决方案是在连接字符串上使用MultipleActiveResultSets=True
:
<add name="ConnectionName" connectionString="[connection string];MultipleActiveResultSets=True" ... />
然后,使用DataTable
代替直接迭代DataReader
:
var dt = new DataTable();
dt.Load(rd);
foreach (DataRow row in dt.Rows)
{
// other stuff
try
{
SqlCommand cmd2 = new SqlCommand(qry2, cn);
cmd2.ExecuteNonQuery();
}
catch (Exception e)
{
// throw exception
}
}
此外,您可以使用SqlConnection.State
属性轻松检查之前的连接是否仍处于打开状态(即提供DataReader
):
// close if connection still open
if (cn.State == ConnectionState.Open)
{
cn.Close();
}
// open if connection already closed
if (cn.State == ConnectionState.Closed)
{
cn.Open();
}
上面的简单检查应该放在请求SqlConnection
的代码的任何部分。