为什么LINQ查询到DataTable不起作用?

时间:2013-03-21 14:05:38

标签: linq c#-4.0 datatable

我有一个DataTable,dt,其中包含以下内容:enter image description here

如您所见,此处有两组文件:基线(第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中删除第3行,但它不会。如果我省略&& 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保持为null,最后一行产生运行时错误:IndexOutOfRangeException: The given DataRow is not in the current DataRowCollection

为什么这不起作用?

1 个答案:

答案 0 :(得分: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();