Доступ к удаленным строкам от DataTable

У меня есть родительский WinForm, который имеет MyDataTable _dt как участник. Тип MyDataTable был создан во "введенном наборе данных" инструмент разработчика в Visual Studio 2005 (MyDataTable наследовался DataTable), _dt заполняется от дб с помощью ADO.NET. На основе изменений от взаимодействия с пользователем в форме я удаляю строку из таблицы как так:

_dt.FindBySomeKey(_someKey).Delete();

Позже, _dt передается значением диалоговой форме. Оттуда, я должен просканировать через все строки для создания строки:

           foreach (myDataTableRow row in _dt)
            {
                sbFilter.Append("'" + row.info + "',");
            }

Проблема состоит в том, что после выполнения этого после удаления, следующее исключение выдается: DeletedRowInaccessibleException: Deleted row information cannot be accessed through the row.

Работа вокруг этого, которое я в настоящее время использую (который чувствует себя подобно взлому) следующая:

           foreach (myDataTableRow  row in _dt)
            {
                if (row.RowState != DataRowState.Deleted &&
                    row.RowState != DataRowState.Detached)
                {
                    sbFilter.Append("'" + row.info + "',");
                }
            }

Мой вопрос: действительно ли это - надлежащий способ сделать это? Почему цикл foreach получил бы доступ к строкам, которые были отмечены через Delete() метод??

7
задан Ken 26 April 2010 в 14:19
поделиться

4 ответа

Вам нужно будет проверить:

 _dt.DefaultView.RowStateFilter

Я думаю, что настройки по умолчанию не будут отображать удаленные строки, возможно, вы измените их где-нибудь.

Вы всегда можете создать дополнительный RowView и управлять его фильтром, а также выполнять цикл над представлением.

2
ответ дан 6 December 2019 в 08:42
поделиться

Метод Delete отмечает строку для удаления; строка фактически не удаляется, пока вы не вызовете AcceptChanges .

Вместо этого вызовите _dt.Rows.Remove (_dt.FindBySomeKey (_someKey)) , который также примет изменение.
Вы не поверите, но Rows.Remove полностью удалит строку, а row.Delete () - не .
Обратите внимание, что если вы вызовете Rows.Remove , строка будет навсегда удалена и не будет удалена из базы данных с помощью DataAdapter.

В C # 3 вы можете заменить оператор if следующим методом расширения:

///<summary>Gets the rows in a typed DataTable that have not been deleted.</summary>
public static EnumerableRowCollection<TRow> CurrentRows<TRow>(this TypedTableBase<TRow> table) where TRow : DataRow { 
    return table.Where(r => r.RowState != DataRowState.Deleted); 
}

foreach (myDataTableRow row in _dt.CurrentRows())
{
    ...

EDIT

Вот версия C # 2:

static class Utils {
    public static IEnumerable<TRow> CurrentRows(IEnumerable<TRow> table) where TRow : DataRow {
        foreach(TRow row in table) {
            if (row.RowState != DataRowState.Deleted)
                yield return row;
        }
    }
}


foreach (myDataTableRow row in Utils.CurrentRows(_dt))
{

Вы также можете поместить эту функцию в частичную класс для типизированной таблицы:

partial class MyTable {
    public IEnumerable<MyRow> CurrentRows() { return Utils.CurrentRows(this); }
}
14
ответ дан 6 December 2019 в 08:42
поделиться

Я не уверен в этом, но думаю, что если вы вызовете _dt.AcceptChanges () после удаления одной или нескольких строк, вы не «увидите» удаленные строки при итерации по коллекции Rows таблиц данных.

0
ответ дан 6 December 2019 в 08:42
поделиться

Используйте GetChanges ():

foreach (myDataTableRow row in _dt.GetChanges(DataRowState.Added))
{
    sbFilter.Append("'" + row.info + "',");
}

Если вы хотите, чтобы все было добавлено и изменено, используйте побитовое ИЛИ для добавленных и измененных:

foreach (myDataTableRow row in
    _dt.GetChanges(DataRowState.Added | DataRowState.Modified))
{
    sbFilter.Append("'" + row.info + "',");
}
1
ответ дан 6 December 2019 в 08:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: