从DataTable访问已删除的行

Ken*_*Ken 7 .net c# datatable c#-2.0

我有一个具有MyDataTable _dt作为成员的父WinForm .MyDataTable类型是在Visual Studio 2005中的"类型化数据集"设计器工具中创建的(MyDataTable继承自DataTable) _dt,通过ADO.NET从db填充.基于表单中用户交互的更改,我从表中删除了一行,如下所示:

_dt.FindBySomeKey(_someKey).Delete();

稍后,_dt将值传递给对话框表单.从那里,我需要扫描所有行来构建一个字符串:

           foreach (myDataTableRow row in _dt)
            {
                sbFilter.Append("'" + row.info + "',");
            }
Run Code Online (Sandbox Code Playgroud)

问题是在删除后执行此操作时,会引发以下异常: 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 + "',");
                }
            }
Run Code Online (Sandbox Code Playgroud)

我的问题:这是正确的方法吗?为什么foreach循环访问通过该Delete()方法标记的行?

SLa*_*aks 14

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())
{
    ...
Run Code Online (Sandbox Code Playgroud)

编辑

这是一个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))
{
Run Code Online (Sandbox Code Playgroud)

您还可以将此函数放入类型表的分部类中:

partial class MyTable {
    public IEnumerable<MyRow> CurrentRows() { return Utils.CurrentRows(this); }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

您在迭代中跳过行的操作是正确的,当我遍历可能被修改的 DataTable 时,我会定期检查 RowState。

在某些情况下,我相信您需要在行被标记为已删除之前的原始行值。检索特定数据行值时有一个二级索引选项。

string st = dr["columnname", DataRowVersion.Original].ToString(); // c#

dim st As String = dr("columnname", DataRowVersion.Original).ToString() ' vb.net
Run Code Online (Sandbox Code Playgroud)

过去我曾多次被困在这个问题上。

就 GetChanges(RowState) 方法而言,不要忘记检查是否返回空值,如果没有该 RowState 的行,则返回的 DataTable 为空(我认为它应该返回一个零行的表)


Hen*_*man 2

您必须检查:

 _dt.DefaultView.RowStateFilter
Run Code Online (Sandbox Code Playgroud)

我认为默认设置不会显示已删除的行,也许您可​​以在某处更改它。

您始终可以创建一个额外的 RowView 并控制其过滤器并在视图上执行循环。