2013-03-21 98 views
-1

我有一個DataTable,DT,包含以下內容:enter image description here爲什麼LINQ查詢DataTable無法正常工作?

正如你所看到的,有兩套文件的位置:基線(列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); 
    } 

這應該從數據表中刪除第3行,但它不」噸。代碼工作正常,如果我省略&& row["STATUS"] == "remove"行,所以我知道它的功能。 baselineSubfolder,baselineFilename和baselineChecksum的值是正確的,所以這不是問題。

但是由於某些原因,當我將狀態列的那一行包括進去時,即使顯然是根據DataSet Visualizer(上圖),它也不會檢測到該行在DataTable中。所以它不會進入foreach循環,也不會刪除必要的文件。爲什麼???

我可能應該提到基線文件信息(前4行)正在從數據庫中檢索,而目標文件字段是根據用戶輸入生成的。我不明白怎麼會身在何處的信息是從哪裏來的,但是,因爲我直接查詢數據表...

UPDATE

好了,下面的idipous和傑米的建議後,基林,我已經確定這個問題與foreach循環有關,而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

爲什麼不是這方面的工作?

+0

在圖片中,狀態是刪除未刪除。不知道是否這是它。 – idipous 2013-03-21 14:09:34

+0

如果我在哪裏我會跟蹤狀態行的值,它會告訴你它作爲一個值的期望值! – Romain 2013-03-21 14:10:50

+0

@idipous是的,這是一個錯字。不是問題,但。它實際上應該是零,但我想知道,如果它是一個空相關的語法問題,所以我改成了「刪除」 – user1985189 2013-03-21 14:11:27

回答

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); 

我也發現了非LINQ的方式來做到這一點,通過DataTable的所有行迭代。這不是最有效的,但它的工作原理:

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();