-1

我有一个 DataTable,dt,它包含以下内容:在此处输入图像描述

如您所见,这里有两组文件:基线(第 1-3 列)和目标(第 4-6 列)。所以在这种情况下,我有 4 个基线文件,m4、m5、m1 和 m3(第 5 行中的 m1 是从第 3 行复制的)和一个目标文件 m1。问题是基线文件 m1.txt 的信息是重复的,所以我尝试使用以下 LINQ 语句将其删除:

var extraneousRows = dt.Rows.Cast<DataRow>().
    Where(
        row => row["BASELINE_FOLDER"] == baselineSubfolder
        && row["BASELINE_FILE"] == baselineFilename
        && row["BASELINE_CHECKSUM"] == baselineChecksum
        && row["STATUS"] == "remove"
    ).ToArray();

foreach (DataRow dr in extraneousRows)
    {
        dt.Rows.Remove(dr);
    }

这应该从 DataTable 中删除第三行,但事实并非如此。如果我省略该 && row["STATUS"] == "remove"行,代码可以正常工作,所以我知道它是有效的。并且baselineSubfolder、baselineFilename 和baselineChecksum 的值是正确的,所以这不是问题所在。

但是由于某种原因,当我包含关于状态列的那一行时,它没有检测到该行在 DataTable 中,即使它显然是根据 DataSet Visualizer(上图)。所以它永远不会进入 foreach 循环,也不会删除必要的文件。为什么???

我可能应该提到基线文件信息(前 4 行)是从数据库中检索的,而目标文件字段是根据用户输入生成的。不过,我看不出信息的来源有什么关系,因为我直接查询 DataTable ......

更新

好的,在遵循 idipous 和 Jamie Keeling 的建议后,我确​​定问题与从未填充过的 foreach 循环有关。因为这个查询应该只返回一行,所以我完全消除了循环。我修改后的代码如下所示:

var extraneousRows = dt.Rows.Cast<DataRow>().
    Where(
        row => row["BASELINE_FOLDER"] == baselineSubfolder
        && row["BASELINE_FILE"] == baselineFilename
        && row["BASELINE_CHECKSUM"] == baselineChecksum
        && row["STATUS"] == "remove"
    ).SingleOrDefault();

dt.Rows.Remove(extraneousRows);

无论出于何种原因, extraneousRows 保持为空,并且最后一行正在生成运行时错误:IndexOutOfRangeException: The given DataRow is not in the current DataRowCollection

为什么这不起作用?

4

1 回答 1

0

实际上,问题在于我需要将列值转换为字符串。解决方案非常简单:只需在列名和中提琴后添加一个 .ToString() !下面的代码就像一个魅力:

var extraneousRows = dt.Rows.Cast<DataRow>().
    Where(
        row => row["BASELINE_FOLDER"].ToString() == baselineSubfolder
        && row["BASELINE_FILE"].ToString() == baselineFilename
        && row["BASELINE_CHECKSUM"].ToString() == baselineChecksum
        && row["STATUS"].ToString() == "remove"
    ).SingleOrDefault();

dt.Rows.Remove(extraneousRows);

通过遍历 DataTable 的所有行,我还找到了一种非 LINQ 方法。这不是最有效的,但它有效:

for (int z = 0; z < dt.Rows.Count; z++)
{
    if ((dt.Rows[z]["BASELINE_FOLDER"].ToString() == baselineSubfolder)
        && (dt.Rows[z]["BASELINE_FILE"].ToString() == baselineFilename)
        && (dt.Rows[z]["BASELINE_CHECKSUM"].ToString() == baselineChecksum)
        && (dt.Rows[z]["STATUS"].ToString() == "remove"))
    {
        dt.Rows[z].Delete();
    }
}
dt.AcceptChanges();
于 2013-03-21T19:16:31.300 回答