#c# #.net #ado.net
#c# #.net #ado.net
Вопрос:
AFAIK вы можете загрузить один набор данных из другого набора данных через 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
}
}
}
Тест проходит, если вы раскомментируете ColumnA . Таким образом, может показаться, что в DataSet.Load() есть ошибка, связанная с тем, что после обнаружения таблицы без столбцов следующая таблица также будет импортирована без столбцов. Обратите внимание, что пустая таблица не затрагивается, только таблица, следующая сразу за ней, поэтому, если только последняя таблица пуста, тест пройдет.
Я нашел ошибку в BCL? Или есть объяснение такому поведению?
Ответ №1:
До того, как я изучил код, я скептически относился к тому, что это может быть ошибкой, но теперь я верю, что это так.
Глядя на DataSet.Load
метод в Reflector, он просматривает предоставленные имена таблиц и создает таблицы, если они не существуют. Поэтому в этом случае он создает таблицы «A», «B» и «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) amp;amp; !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
reader (in FillNextResult
), но нет else
вызова NextResult
, если значение FieldCount
равно 0, и это приводит к тому, что все впоследствии не синхронизируется.
Комментарии:
1. Хорошая находка — это определенно объясняет это. Я подниму заявку на подключение.
2. Обновить: connect.microsoft.com/VisualStudio/feedback/details/695262/…