重试DbDataAdapter.重新连接后填充

本文关键字:填充 重新连接 DbDataAdapter 重试 | 更新日期: 2023-09-27 17:50:18

我有一个代码来填写从数据库使用SqlCommand与选择sql和DbDataAdapter的数据表。在向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 = 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()

我有两个问题:

  1. 为什么table.Rows.Clear()会导致这样的行为差异?它是如何关闭DataReader的?

  2. 如何解决?我需要清除已经加载的行并重新填充表。

重试DbDataAdapter.重新连接后填充

好的,我已经找到了问题,它是在我的测试代码。我在加载特定行数时手动关闭连接,清理表并重新填充后,连接再次关闭,触发新的未处理异常