已经有一个与此命令关联的打开的 DataReader,没有嵌套的 DataReader
There is already an open DataReader associated with this Command, without nested datareaders
我间歇性地收到以下错误。
已经有一个打开的 DataReader 与此命令关联,必须先将其关闭。
我了解到当同一连接中有嵌套的 DataReader 时会发生这种情况,但就我而言,我使用以下代码来执行所有查询。
private SqlTransaction Transaction { get; set; }
private SqlConnection Connection { get; set; }
private DbRow Row {get; set;}
public Row Exec(string sql){
try{
//Begin connection/transaction
Connection = new SqlConnection(connectionString);
Connection.Open();
Transaction = Connection.BeginTransaction("SampleTransaction");
//create command
SqlCommand command = new SqlCommand(sql, Connection);
command.Transaction = Transaction;
//execute reader and close it
//HERE IS THE PROBLEM, THE READER ALWAYS READ UNTIL THE END
//BEFORE ANOTHER CAN BE OPENED
reader = command.ExecuteReader();
while (reader.Read())
{
object[] value = new object[reader.FieldCount];
reader.GetValues(value);
List<object> values = new List<object>(value);
Rows.Add(values);
}
reader.Close();
Transaction.Commit();
Connection.Dispose();
Connection = null;
}
catch
{
Transaction.Rollback();
Connection.Dispose();
Connection = null;
}
finally
{
if (reader != null && !reader.IsClosed) reader.Close();
}
}
这样,结果存储在一个对象中,没有嵌套的读者。
我还读到在连接字符串中添加 'MultipleActiveResultSets=True' 可以解决使用嵌套阅读器时的问题。
这个解决方案是否也解决了我的问题?
由于错误是间歇性的,而且只在生产环境中出现,所以我无法多次测试。
There is already an open DataReader associated with this Command which must be closed first. at
System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) at
System.Data.SqlClient.SqlInternalTransaction.Rollback() at
System.Data.SqlClient.SqlTransaction.Rollback() at
Application.Lib.DB.DBSQLServer.Rollback()
at Application.Lib.DB.DBSQLServer.Execute(String sql, Dictionary`2 parameters,
Nullable`1 timeout, Boolean useTransaction) at
Application.UtilDB.Execute(String sql, Dictionary`2 parameters, Nullable`1
timeout, Boolean useTransaction) in c:\Application\DBUtil.cs:line 37 at
Application.A.CollectionFromDataBase(Int32 cenId,
IDB db, Int32 includeId, Boolean allStatus) in c:\Application\Activities.cs:line 64 at
Application.ActivitiesController.CheckForConflictsBeforeSave(String aulId, String insId) in c:\Application\AlocController.cs:line 212
由于这种情况只发生在生产环境中,所以错误更有可能出在您附加的代码之外。
防止这种情况的最常见方法是始终按以下方式编码:
reader = command.ExecuteReader();
try
{
for (int i = 0; i < reader.FieldCount; i++)
{
dbResult.Columns.Add(reader.GetName(i));
dbResult.Types.Add(reader.GetDataTypeName(i));
}
while (reader.Read())
{
object[] value = new object[reader.FieldCount];
reader.GetValues(value);
List<object> values = new List<object>(value);
Rows.Add(values);
}
}
finally
{
reader.Close();
}
注意 finally
块,它确保 reader 无论如何都关闭。我的印象是您的代码中发生了某些事情,导致 reader 打开,但错误在您发布的代码中不可见。
我建议你把它放在上面的 try/finally 块中 你的错误很可能会得到解决.
编辑,以澄清:这可能无法解决原始代码范围之外存在的任何错误,但它会阻止数据 readers 保持打开状态。我建议的 finally
块不会阻止任何异常,它们将传播到您在它之外使用的任何处理程序。
问题是,当查询失败时,事务无法回滚,因为数据 reader 已经打开以处理查询。
抛出第二个异常,第一个异常丢失。
我只是将回滚放在 try catch 块中并使用 AggregateException class 抛出两个异常。
try
{
Transaction.Rollback();
Connection.Dispose();
Connection = null;
}
catch (Exception ex2)
{
throw new AggregateException(new List<Exception>() { e, ex2 });
}
虽然事务无论如何都会被回滚,但我想你也可以尝试在回滚前关闭数据reader,所以它可能会起作用。
if (reader != null && !reader.IsClosed)
reader.Close();
Transaction.Rollback();
我间歇性地收到以下错误。 已经有一个打开的 DataReader 与此命令关联,必须先将其关闭。
我了解到当同一连接中有嵌套的 DataReader 时会发生这种情况,但就我而言,我使用以下代码来执行所有查询。
private SqlTransaction Transaction { get; set; }
private SqlConnection Connection { get; set; }
private DbRow Row {get; set;}
public Row Exec(string sql){
try{
//Begin connection/transaction
Connection = new SqlConnection(connectionString);
Connection.Open();
Transaction = Connection.BeginTransaction("SampleTransaction");
//create command
SqlCommand command = new SqlCommand(sql, Connection);
command.Transaction = Transaction;
//execute reader and close it
//HERE IS THE PROBLEM, THE READER ALWAYS READ UNTIL THE END
//BEFORE ANOTHER CAN BE OPENED
reader = command.ExecuteReader();
while (reader.Read())
{
object[] value = new object[reader.FieldCount];
reader.GetValues(value);
List<object> values = new List<object>(value);
Rows.Add(values);
}
reader.Close();
Transaction.Commit();
Connection.Dispose();
Connection = null;
}
catch
{
Transaction.Rollback();
Connection.Dispose();
Connection = null;
}
finally
{
if (reader != null && !reader.IsClosed) reader.Close();
}
}
这样,结果存储在一个对象中,没有嵌套的读者。 我还读到在连接字符串中添加 'MultipleActiveResultSets=True' 可以解决使用嵌套阅读器时的问题。 这个解决方案是否也解决了我的问题? 由于错误是间歇性的,而且只在生产环境中出现,所以我无法多次测试。
There is already an open DataReader associated with this Command which must be closed first. at
System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) at
System.Data.SqlClient.SqlInternalTransaction.Rollback() at
System.Data.SqlClient.SqlTransaction.Rollback() at
Application.Lib.DB.DBSQLServer.Rollback()
at Application.Lib.DB.DBSQLServer.Execute(String sql, Dictionary`2 parameters,
Nullable`1 timeout, Boolean useTransaction) at
Application.UtilDB.Execute(String sql, Dictionary`2 parameters, Nullable`1
timeout, Boolean useTransaction) in c:\Application\DBUtil.cs:line 37 at
Application.A.CollectionFromDataBase(Int32 cenId,
IDB db, Int32 includeId, Boolean allStatus) in c:\Application\Activities.cs:line 64 at
Application.ActivitiesController.CheckForConflictsBeforeSave(String aulId, String insId) in c:\Application\AlocController.cs:line 212
由于这种情况只发生在生产环境中,所以错误更有可能出在您附加的代码之外。
防止这种情况的最常见方法是始终按以下方式编码:
reader = command.ExecuteReader();
try
{
for (int i = 0; i < reader.FieldCount; i++)
{
dbResult.Columns.Add(reader.GetName(i));
dbResult.Types.Add(reader.GetDataTypeName(i));
}
while (reader.Read())
{
object[] value = new object[reader.FieldCount];
reader.GetValues(value);
List<object> values = new List<object>(value);
Rows.Add(values);
}
}
finally
{
reader.Close();
}
注意 finally
块,它确保 reader 无论如何都关闭。我的印象是您的代码中发生了某些事情,导致 reader 打开,但错误在您发布的代码中不可见。
我建议你把它放在上面的 try/finally 块中 你的错误很可能会得到解决.
编辑,以澄清:这可能无法解决原始代码范围之外存在的任何错误,但它会阻止数据 readers 保持打开状态。我建议的 finally
块不会阻止任何异常,它们将传播到您在它之外使用的任何处理程序。
问题是,当查询失败时,事务无法回滚,因为数据 reader 已经打开以处理查询。
抛出第二个异常,第一个异常丢失。
我只是将回滚放在 try catch 块中并使用 AggregateException class 抛出两个异常。
try
{
Transaction.Rollback();
Connection.Dispose();
Connection = null;
}
catch (Exception ex2)
{
throw new AggregateException(new List<Exception>() { e, ex2 });
}
虽然事务无论如何都会被回滚,但我想你也可以尝试在回滚前关闭数据reader,所以它可能会起作用。
if (reader != null && !reader.IsClosed)
reader.Close();
Transaction.Rollback();