The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

解決【由於該物件目前的狀態,導致作業無效。】問題

如果你用 LINQ to SQL 開發系統的話,若兩個關連的表格需要更新資料,但需要更新的資料是 Foreign Key 的值的話,就有些地方需要特別注意,由於透過 LINQ to SQL 讀取或寫入資料都是透過 ORM ( Object-relational mapping ) 的方式儲存,讓原本在資料庫中的資料改以物件的方式表達,因此對這種包含關連的物件,就不能像用 T-SQL 的方式一樣改變關連的鍵值。

例如說我有兩個關連的表格如下:

兩個關連的表格

其中分區區域的表格內容是:

ID = 1 , Name = 北
ID = 2 , Name = 中
ID = 3 , Name = 南
ID = 4 , Name = 東
ID = 5 , Name = 離島

而分區縣市就是台灣 25 縣市的資料,假設我要將「桃園市」的「分區區域ID」從 1 改成 5 的話,若使用 T-SQL 更新還蠻容易的,如下:

UPDATE 分區縣市 SET 分區區域ID=5 WHERE ID=6

不過,若你要用 LINQ to SQL 的方式更新,一般人可能會很直覺的這樣寫:

MyDataContext db = new MyDataContext();
var city1 = (from p in db.分區縣市 where p.ID == 6 select p).Single();
city1.分區區域ID = 5;
db.SubmitChanges();

如果你這樣寫的話,恭喜你,你將獲得【System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException: 由於該物件目前的狀態,導致作業無效。】的錯誤訊息。(英文版的訊息是 Operation is not valid due to the current state of the object

System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException: 由於該物件目前的狀態,導致作業無效。 / Operation is not valid due to the current state of the object

昨天我同事問我這問題時,我想了一下 ORM 的邏輯,當下就覺得如果這種寫法可行的話,應該會破壞 ORM 的關連結構,導致物件之間的關係錯亂。所以我改用以下方式寫:

MyDataContext db = new MyDataContext();
var city1 = (from p in db.分區縣市 where p.ID == 6 select p).Single();
city1.分區區域 = db.分區區域.Single(p => p.ID == 5);
db.SubmitChanges();
果然一試就成功。