DataTable выбрасывает исключение на RejectChanges - PullRequest
4 голосов
/ 19 марта 2012

Я обнаружил эту ошибку при работе с DataTable.Я добавил столбец первичного ключа в DataTable, затем добавил одну строку в эту таблицу, удалил эту строку и добавил в таблицу строку с тем же ключом.Это работает.Когда я попытался вызвать RejectChanges(), я получил ConstraintException, сказав, что значение уже присутствует.Вот пример:

    var dataTable = new DataTable();
    var column = new DataColumn("ID", typeof(decimal));
    dataTable.Columns.Add(column);
    dataTable.PrimaryKey =  new [] {column };

    decimal id = 1;

    var oldRow = dataTable.NewRow();
    oldRow[column] = id;

    dataTable.Rows.Add(oldRow);
    dataTable.AcceptChanges();

    oldRow.Delete();

    var newRow = dataTable.NewRow();
    newRow[column] = id;

    dataTable.Rows.Add(newRow);
    dataTable.RejectChanges(); // This is where it crashes

Я думаю, что поскольку строка удалена, исключение не должно создаваться (ограничение не нарушается, поскольку строка находится в удаленном состоянии).Что я могу с этим поделать?Любая помощь приветствуется.

Ответы [ 2 ]

3 голосов
/ 19 марта 2012

Я предполагаю, что это имеет ту же причину, что и следующая ошибка, так как первое, что будет отклонено, это ваше delete действие:

DataTable.RejectChanges () должен выполнить откат строк в обратном порядке

Два возможных обходных пути:

Циклически перебирает DataRows в обратном порядке. Итак новые записи удаляются, прежде чем предыдущие возвращаются в жизнь.

DataRowCollection rows = dataTable.Rows;
for (int i = rows.Count - 1; i >= 0; i--)
{
    rows[i].RejectChanges();
}

Отключает ограничения, чтобы можно было выполнить откат. Reenables ограничивает после этого.

  1. Вы можете использовать LINQ-to-DataSet, чтобы определить свой собственный «порядок отката»:

    var rollbackPlan = (from r in dataTable.AsEnumerable()
                   where r.RowState != DataRowState.Unchanged
                   let firstOrder  = r.RowState==DataRowState.Deleted? 1 : 0
                   let secondOrder = r.RowState==DataRowState.Added?   1 : 0
                   orderby firstOrder ascending, secondOrder ascending
                   select r).ToList();
    foreach (DataRow r in rollbackPlan)
    {
        r.RejectChanges(); // Does not crash anymore
    }
    
  2. Вот как вы временно «отключаете» ограничения для DataTable:

    var constraintBackup = dataTable.Constraints.Cast<System.Data.Constraint>().ToList();
    dataTable.Constraints.Clear();
    dataTable.RejectChanges(); // Does not crash anymore
    foreach (System.Data.Constraint c in constraintBackup)
    {
        dataTable.Constraints.Add(c);
    }
    
0 голосов
/ 19 марта 2012

Этого можно избежать, используя unique свойство столбца tor true.

т.е. column.Unique = true;

Как только это свойство будет изменено на true, будет установлено уникальное ограничениеВ этом столбце необходимо создать уникальные значения.

...