枚举 DataTable,筛选项目,然后恢复为 DataTable

3
我希望能够通过将DataTable转换为IEnumerable<DataRow>,然后按照列值是否包含在字符串数组中来筛选项目,最后再将其重新转换为DataTable,因为这是我的方法必须返回的内容。
以下是我目前的代码:
string[] ids = /*Gets string array of IDs here*/
DataTable dt = /*Databasecall returning a DataTable here*/
IEnumerable<DataRow> ie = dt.AsEnumerable();
ie = ie.Where<DataRow>(row => ids.Contains(row["id"].ToString()));
/*At this point I've filtered out the entries I don't want, now how do I convert this back to a DataTable? The following does NOT work.*/
ie.CopyToDataTable(dt, System.Data.LoadOption.PreserveChanges);
return dt;

我正在进行分配,请检查第一个参数。 - Dennis Röttger
我已经得到了答案,应该删除评论,抱歉。 - Orkun
但是,仍然第一个参数应该是“源”...我认为你需要将dt分配给“结果”...(我有什么遗漏吗?) - Orkun
第一个参数是目标。 - Dennis Röttger
2
这是一个扩展方法,当然第一个参数是源对象,但第一个参数也是 IEnumerable 而不是 DataTable,你会发现实际上 DataTable 是作为目标对象的。 - Dennis Röttger
显示剩余2条评论
2个回答

1
假设您想要在原地过滤行,也就是说,过滤后的行应该在通过原始数据库查询创建的相同 DataTable 中返回,您应该首先清除 DataTable.Rows 集合。然后,您应该将过滤后的行复制到一个数组中,并按顺序添加它们:
ie = ie.Where<DataRow>(row => ids.Contains(row["id"].ToString())).ToArray();
dt.Rows.Clear();

foreach (var row in ie)
{
    dt.Rows.Add(row);
}

另一种实现此目标的替代方法是仅遍历 DataTable中的行并删除应该被过滤掉的行:

foreach (var row in dt.Rows)
{
    if (ids.Contains(row["id"].ToString()) == false)
    {
        row.Delete();
    }
}

dt.AcceptChanges();

请注意,如果DataTableDataSet的一部分,并且正在用于更新数据库,则对DataTable.Rows集合所做的所有修改都将在更新期间反映在相应的数据库表中。

1
当我清空我的DataTable时,我的IEnumerable也被清空了。 当我在ForEach循环内迭代每一行并删除它时,我会收到一个错误,因为我在迭代过程中改变了集合(逻辑上)。使用for循环或创建第二个DataTable肯定是选项,但我正在寻找一些更简洁的东西。 - Dennis Röttger
@DennisRöttger 为什么你认为创建一个新表比改变现有表更加不干净? - Rune FS
@DennisRöttger 正确。我修改了我的示例,使用DataRow.Delete()方法,这个方法不会立即生效,直到您调用DataTable.AcceptChanges()方法。 - Enrico Campidoglio
我认为将要过滤的对象的数据转换为允许过滤的类型,然后执行过滤操作,最后再将数据转换回原始对象,这样做感觉很自然,你不同意吗? - Dennis Röttger
@DennisRöttger 我还通过将要筛选的行序列复制到数组中来更正了我的第一个示例。 - Enrico Campidoglio

1
我会创建一个空的数据表克隆:
DataTable newTable = dt.Clone();

然后导入与过滤器匹配的旧表中的行:

foreach(DataRow row in ie)
{
    newTable.ImportRow(row);
}

这就是我现在所采取的做法,我希望有一种更优雅的解决方案,可以利用原始的 DataTable。 - Dennis Röttger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接