ADO.. NET DataSet.Load()似乎不能正确处理空表

本文关键字:不能 正确处理 NET DataSet Load ADO | 更新日期: 2023-09-27 18:11:15

您可以通过IDataReader从另一个数据集加载一个数据集,即

new DataSet().Load(existingDataSet.CreateDataReader());
// should now have two DataSets with the same contents

我还没有找到任何文档表明这是不可能的。有人能解释一下,为什么下面的NUnit测试失败了吗?

[Test]
public void Should_be_able_to_load_one_dataset_from_another()
{
    var tableA = new DataTable("A");
    //tableA.Columns.Add("ColumnA", typeof(int));
    var tableB = new DataTable("B");
    tableB.Columns.Add("ColumnB", typeof(int));
    var tableC = new DataTable("C");
    using (var original = new DataSet())
    {
        original.Tables.Add(tableA);
        original.Tables.Add(tableB);
        original.Tables.Add(tableC);
        using (var expectedReader = original.CreateDataReader())
        using (var actual = new DataSet())
        {
            actual.Load(expectedReader, LoadOption.OverwriteChanges, "A", "B", "C");
            Assert.That(actual.HasErrors, Is.False);
            for (var i = 0; i < original.Tables.Count; i++)
                Assert.That(actual.Tables[i].Columns.Count, Is.EqualTo(original.Tables[i].Columns.Count), 
                    "Table {0} had the wrong number of columns.", i); // fails here
        }
    }
}

如果取消对列a的注释,则测试通过。因此,似乎在DataSet.Load()中可能存在一个错误,即在遇到没有列的表后,将导入没有列的下一个表。注意空表不受影响,只有紧跟着它的表才受影响,所以如果只有最后一个表为空,测试将通过。

我在BCL中发现了一个bug吗?或者对这种行为有解释吗?

ADO.. NET DataSet.Load()似乎不能正确处理空表

在我查看代码之前,我怀疑这可能是一个bug,但现在我相信它是。

查看Reflector中的DataSet.Load方法,它遍历提供的表名,如果表不存在,则创建表。因此,在本例中,它创建了表"A", "B"answers"C"。

然后加载数据,通过以下方法调用并将目标数据集中的目标表作为DataTable[]传递:

  • DataSet.Load(IDataReader, LoadOption, FillErrorEventHandler, params DataTable[])
  • LoadAdapter.FillFromReader(DataTable[], IDataReader, int, int)
  • LoadAdapter.Fill(DataTable[], IDataReader, int, int)

在最后一个Fill方法中,它循环遍历DataTable[]来填充每个表,但它只填充包含字段的表:

if (container.FieldCount > 0)
{
    if ((0 < i) && !this.FillNextResult(container))
    {
        goto Label_00DE;
    }
    int num4 = this.FillFromReader(null, dataTables[i], null, container, startRecord, maxRecords, null, null);
    if (i == 0)
    {
        num2 = num4;
    }
}

请注意,当它填充表时,它也会在读取器上调用NextResult(在FillNextResult中),但是如果FieldCount为0,则没有else来调用NextResult,这会导致之后的所有内容不同步。