我有一个代码,使用带有select sql和DbDataAdapter的SqlCommand从db填充DataTable。在向DataTable填充行期间,有时会丢失DbConnection,这会被处理并调用adapter.Fill()的第二次尝试:
int FillSafe(DataTable dataTable)
{
try
{
return adapter.Fill(dataTable);
}
catch (Exception ex)
{
if (connectionErrorManager.HandleDisconnectionAndSecurityErrors(ex))
{
// Re-try fill function if error was properly handled
return adapter.Fill(dataTable);
}
throw;
}
}
adapter是使用命令
初始化的本地字段adapter = new SqlDataAdapter((SqlCommand)selectCommand);
connectionErrorManager.HandleDisconnectionAndSecurityErrors()基本上关闭并重新打开SqlConnection对象(同一实例)。
它似乎工作正常,但是没有主键的表存在问题 - 某些数据行在DataTable中变得重复。 即以下测试失败,有5行而不是3行:
public void TestFillDoesnotProduceDuplicateRowsAfterDisconnect()
{
const string Query = @"
SELECT 'A'
UNION ALL
SELECT 'B'
UNION ALL
SELECT 'C'";
var table = new DataTable();
table.RowChanged += (o, e) =>
{
if (table.Rows.Count == 2)
{
Db.Connection.CloseConnection();
}
};
using (var command = Db.Connection.Command(Query))
using (var adapter = command.NewDataAdapter())
{
FillSafe(table);
}
AssertEquals(3, table.Rows.Count);
}
如果我在重新填充之前尝试清除DataTable
table.Rows.Clear();
测试失败,关闭DataReader的例外:
Exception Type: System.InvalidOperationException
Message: Invalid attempt to call Read when reader is closed.
StackTrace:
at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
at System.Data.SqlClient.SqlDataReader.Read()
at System.Data.Common.DataAdapter.FillLoadDataRow(SchemaMapping mapping)
at System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)
at className.FillSafe[T](DataTable dataTable)
at className.TestFillDoesnotProduceDuplicateRowsAfterDisconnect()
所以我有两个问题:
为什么table.Rows.Clear()会导致行为上的这种差异?它是如何关闭DataReader的?
如何解决?我需要清除已经加载的行并重新填充表格。
答案 0 :(得分:0)
好的,我发现了这个问题,它出现在我的测试代码中。 我在加载特定行数时手动关闭连接,清理表格和重新填充后,连接再次关闭,触发新的未处理异常。