一步一步學Linq to sql(七):并發與事務
系列文章導航:
一步一步學Linq to sql(二):DataContext與實體
檢測并發
首先使用下面的SQL語句查詢數據庫的產品表:
select * from products where categoryid=1 |
查詢結果如下圖:
為了看起來清晰,我已經事先把所有分類為1產品的價格和庫存修改為相同值了。然后執行下面的程序:
var query = from p in ctx.Products where p.CategoryID == 1 select p; foreach (var p in query) p.UnitsInStock = Convert.ToInt16(p.UnitsInStock - 1); ctx.SubmitChanges(); // 在這里設斷點 |
我們使用調試方式啟動,由于設置了斷點,程序并沒有進行更新操作。此時,我們在數據庫中運行下面的語句:
update products set unitsinstock = unitsinstock -2, unitprice= unitprice + 1 where categoryid = 1 |
然后在繼續程序,會得到修改并發(樂觀并發沖突)的異常,提示要修改的行不存在或者已經被改動。當客戶端提交的修改對象自讀取之后已經在數據庫中發生改動,就產生了修改并發。解決并發的包括兩步,一是查明哪些對象發生并發,二是解決并發。如果你僅僅是希望更新時不考慮并發的話可以關閉相關列的更新驗證,這樣在這些列上發生并發就不會出現異常:
[Column(Storage="_UnitsInStock", DbType="SmallInt", UpdateCheck = UpdateCheck.Never)] [Column(Storage="_UnitPrice", DbType="Money", UpdateCheck = UpdateCheck.Never)] |
為這兩列標注不需要進行更新檢測。假設現在產品價格和庫存分別是27和32。那么,我們啟動程序(設置端點),然后運行UPDATE語句,把價格+1,庫存-2,然后價格和庫存分別為28和30了,繼續程序可以發現價格和庫存分別是28和31。價格+1是之前更新的功勞,庫存最終是-1是我們程序之后更新的功勞。當在同一個字段上(庫存)發生并發沖突的時候,默認是最后的那次更新獲勝。