我有一个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中删除第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
为什么这不起作用?
答案 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();