【问题标题】:Accessing deleted rows from a DataTable从 DataTable 访问已删除的行
【发布时间】:2010-04-26 14:19:25
【问题描述】:

我有一个父 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.

我目前正在使用的解决方法(感觉像是 hack)如下:

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

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

【问题讨论】:

  • 你不需要检查Detached

标签: c# .net datatable c#-2.0


【解决方案1】:

Delete method 标记要删除的行;在您调用 AcceptChanges 之前,该行实际上不会被删除。

请改为致电_dt.Rows.Remove(_dt.FindBySomeKey(_someKey)),它也会接受更改。
信不信由你,Rows.Remove will completely remove the row, whereas row.Delete() won't。 罢工> 请注意,如果您调用 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.Update() Update() 是否知道要使用 DeleteCommand 删除这一行,还是“一去不复返”?
  • @Ken:不,已删除的行将不会在更新期间被删除。删除!= 删除
  • @Ken:好点;我假设调用 remove 将导致 Update 不删除它。试试看。
  • @SLaks - 调用 Remove 会导致更新不会在数据库中删除它。此外,C#3 对我无效(使用 2.0),但感谢您的输入!
  • @Slaks 你的 C# 2 版本不正确 => public static IEnumerable CurrentRows(this IEnumerable table) where TRow : DataRow { foreach(TRow row in table) { if (row.RowState != DataRowState.Deleted) 产生返回行; } }
【解决方案2】:

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

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

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

dim st As String = dr("columnname", DataRowVersion.Original).ToString() ' vb.net

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

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

【讨论】:

    【解决方案3】:

    您必须检查:

     _dt.DefaultView.RowStateFilter
    

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

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

    【讨论】:

    • 这不会影响表的枚举数。
    • @Slaks:我写道:'然后循环查看'
    • @Henk:我最终像这样循环了 DataView(默认情况下不包含已删除的记录):foreach (DataRowView row in _dt.DefaultView ) { sbFilter.Append("'" + ((myDataTableRow)row.Row).info+ "',"); } 在提供的所有选项中,我认为这是最干净的方法。谢谢!
    【解决方案4】:

    使用 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 + "',");
    }
    

    【讨论】:

    • 不错,但这实际上会产生编译器错误,因为 DataTable 不包含公共 GetEnumerator() 方法。
    • 这不会返回未更改的行。
    • @SLaks:尽管名称为 GetChanges,但您可以获得未更改的行,_dt.GetChanges(DataRowSate.Unchanged)
    【解决方案5】:

    我不确定这一点,但我认为如果您在删除一行或多行后调用 _dt.AcceptChanges(),则在遍历数据表的 Rows 集合时将不会“看到”已删除的行。

    【讨论】:

    • AcceptChanges 删除行状态,稍后当我执行 _dt.Update() 将更改持久化回数据库时,我需要此状态。我可能会在更新后调用 AcceptChanges()。谢谢!
    猜你喜欢
    • 2021-08-18
    • 2015-06-13
    • 2016-09-10
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 2011-08-08
    相关资源
    最近更新 更多