Редактировать: любые комментарии, если вы считаете, что это ошибка .NET или нет, приветствуются.
У меня есть ошибка, которую мне удалось упростить до следующего сценария:
У меня есть DataTable, где первичные ключи должны храниться последовательно, например, если вы вставляете строку между другими строками, вы должны сначала увеличить ID последующих строк, чтобы освободить место, а затем вставить строку.
И если вы удаляете строку, вы должны уменьшить ID всех последующих строк, чтобы заполнить пробел, оставленный строкой в таблице.
Тестовый пример, который работает правильно
Начните с 3 строк в таблице, с идентификаторами 1, 2 и 3.
Затем удалите ID = 2 и установите ID = 2, где ID = 3 (чтобы заполнить пробел); это работает правильно. DataTable.GetChanges () содержит удаленную строку, а затем измененную строку; когда вы запускаете dataAdapter.Update (таблица), он работает нормально.
Тестовый пример, который не работает
Однако, если вы начнете с 2 строк (идентификаторы 1 и 2), затем установите ID = 3, где ID = 2, и вставьте ID = 2, затем подтвердите (или примите) изменения. Теперь это состояние должно совпадать с первым тестом.
Затем вы делаете те же шаги, что и раньше, то есть удаляете ID = 2 и устанавливаете ID = 2, где ID = 3, но теперь dataTable.GetChanges () находятся в неправильном порядке. Первая строка является измененной строкой, а вторая строка является удаленной строкой. Затем, если вы попробуете dataAdapter.Update (таблица), это приведет к нарушению первичного ключа - он попытался изменить строку до уже существующей строки перед удалением.
Обход
Я могу придумать обходной путь к проблеме, то есть заставить его так, чтобы сначала удалялись удаленные строки, а затем измененные строки, а затем добавленные строки. Но почему это происходит? Есть ли другое решение?
Мне кажется, я уже сталкивался с подобной «проблемой» со словарями: если вы добавляете некоторые элементы, удаляете их, вставляете их заново, то они не будут в той же последовательности, в которой вы их добавляли (при перечислении словарь).
Вот два теста NUnit, которые показывают проблему:
[Test]
public void GetChanges_Working()
{
// Setup ID table with three rows, ID=1, ID=2, ID=3
DataTable idTable = new DataTable();
idTable.Columns.Add("ID", typeof(int));
idTable.PrimaryKey = new DataColumn[] { idTable.Columns["ID"] };
idTable.Rows.Add(1);
idTable.Rows.Add(2);
idTable.Rows.Add(3);
idTable.AcceptChanges();
// Delete ID=2, and move old ID=3 to ID=2
idTable.Select("ID = 2")[0].Delete();
idTable.Select("ID = 3")[0]["ID"] = 2;
// Debug GetChanges
foreach (DataRow row in idTable.GetChanges().Rows)
{
if (row.RowState == DataRowState.Deleted)
Console.WriteLine("Deleted: {0}", row["ID", DataRowVersion.Original]);
else
Console.WriteLine("Modified: {0} = {1}", row["ID", DataRowVersion.Original], row["ID", DataRowVersion.Current]);
}
// Check GetChanges
Assert.AreEqual(DataRowState.Deleted, idTable.GetChanges().Rows[0].RowState, "1st row in GetChanges should be deleted row");
Assert.AreEqual(DataRowState.Modified, idTable.GetChanges().Rows[1].RowState, "2nd row in GetChanges should be modified row");
}
Выход:
Deleted: 2
Modified: 3 = 2
1 passed, 0 failed, 0 skipped, took 4.27 seconds (NUnit 2.4).
Следующий тест:
[Test]
public void GetChanges_NotWorking()
{
// Setup ID table with two rows, ID=1, ID=2
DataTable idTable = new DataTable();
idTable.Columns.Add("ID", typeof(int));
idTable.PrimaryKey = new DataColumn[] { idTable.Columns["ID"] };
idTable.Rows.Add(1);
idTable.Rows.Add(2);
idTable.AcceptChanges();
// Move old ID=2 to ID=3, and add ID=2
idTable.Select("ID = 2")[0]["ID"] = 3;
idTable.Rows.Add(2);
idTable.AcceptChanges();
// Delete ID=2, and move old ID=3 to ID=2
idTable.Select("ID = 2")[0].Delete();
idTable.Select("ID = 3")[0]["ID"] = 2;
// Debug GetChanges
foreach (DataRow row in idTable.GetChanges().Rows)
{
if (row.RowState == DataRowState.Deleted)
Console.WriteLine("Deleted: {0}", row["ID", DataRowVersion.Original]);
else
Console.WriteLine("Modified: {0} = {1}", row["ID", DataRowVersion.Original], row["ID", DataRowVersion.Current]);
}
// Check GetChanges
Assert.AreEqual(DataRowState.Deleted, idTable.GetChanges().Rows[0].RowState, "1st row in GetChanges should be deleted row");
Assert.AreEqual(DataRowState.Modified, idTable.GetChanges().Rows[1].RowState, "2nd row in GetChanges should be modified row");
}
Выход:
Modified: 3 = 2
Deleted: 2
TestCase 'GetChanges_NotWorking'
failed:
1st row in GetChanges should be deleted row
Expected: Deleted
But was: Modified