У меня есть родительский 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()
метод??
Вам нужно будет проверить:
_dt.DefaultView.RowStateFilter
Я думаю, что настройки по умолчанию не будут отображать удаленные строки, возможно, вы измените их где-нибудь.
Вы всегда можете создать дополнительный RowView и управлять его фильтром, а также выполнять цикл над представлением.
Метод 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())
{
...
Вот версия 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); }
}
Я не уверен в этом, но думаю, что если вы вызовете _dt.AcceptChanges ()
после удаления одной или нескольких строк, вы не «увидите» удаленные строки при итерации по коллекции Rows таблиц данных.
Используйте 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 + "',");
}