來一個好網址, 微軟官方的例子。 真搞不懂微軟怎麼不把資源好好理一下,找個東西真難。
http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx
首先來看一看一個代碼:
NorthwindDataContext ctx = new NorthwindDataContext();
Customer alfki = ctx.Customers.Single(c => c.CustomerID == "ALFKI");
Console.WriteLine("Before update, the company name of Alfki is: " + alfki.CompanyName);
alfki.CompanyName = "New Company Name";
Customer newAlfki = ctx.Customers.Single(c => c.CustomerID == "ALFKI");
Console.WriteLine("Before submit changes, the company name of Alfki is: " + alfki.CompanyName);
ctx.SubmitChanges();
出來的代碼肯定想不到。
Before update, the company name of Alfki is: Alfreds Futterkiste
Before submit changes, the company name of Alfki is: New Company Name
可以看到,第二次查詢是在更新提交之前,這時候資料庫中的值還沒有改變,按理說這時候去進行資料庫查詢得到的值應該還是舊值,但是代碼運行後發現查詢出來的值確是更新後的值。這是為什麼呢?其實原因還是上篇提到過的Identity Cache,DataContext以主鍵為key對資料對象進行緩衝以此對資料對象的生命週期進行跟蹤。藉助Sql profile可以發現,第二次調用ctx.Customers.Single時,資料庫並沒有查詢的記錄,這裡DataContext直接在記憶體中尋找該對象並且返回。當然也可以關閉這種機制,只需要調用ctx.ObjectTrackingEnabled = false。DataContext就不再對資料對象進行Identity Cache,每次查詢結果都是通過查詢資料庫得到。其實上面的這些跟更新沒什麼關係。但它主要是講明了一個道理:當你在查詢資料的時候得小心。因為很可能查到的是錯誤的資料。
資料庫資料更新通常會遇到同步衝突的問題,比如獲得資料以後,對資料進行一系列的操作,然後把新的資料更新回資料庫。如果在資料進行操作的同時,有其它程式或者管理員改動了該資料的值,這樣就會發生衝突。到底資料是應該保留現有的值呢還是把改動的值強行更新到資料庫呢?Linq to SQL提供了很多方法來解決這種衝突問題。
還是一段簡單的更新代碼:
NorthwindDataContext ctx = new NorthwindDataContext();
Customer alfki = ctx.Customers.Single(c => c.CustomerID == "ALFKI");
alfki.CompanyName = "New Company Name";
ctx.SubmitChanges();
在SubmitChanges()加上斷點然後運行,接著在資料庫管理員中修改這條記錄的CompanyName,最後回到vs介面,繼續往下運行,這時會拋出ChangeConflictException,提示該行記錄已經被刪除或者被修改
在Linq to SQL中,解決衝突有幾種方法:
- 在映射欄位的Column Attribute中添加UpdateCheck屬性
[Column(Storage="_CompanyName", DbType="NVarChar(40) NOT NULL", CanBeNull=false, UpdateCheck=UpdateCheck.Never)]public string CompanyName {
UpdateCheck的意思是在更新的時候是否檢查衝突,分為三種,根據自己的需求進行選擇:
- Always 始終檢查
- Never 從不檢查
- WhenChanged 當資料有改動的時候檢查
2. 使用ObjectChangeConflict的Resolve方法,比如:
try {ctx.SubmitChanges();}catch (ChangeConflictException){foreach (ObjectChangeConflict confict in ctx.ChangeConflicts){confict.Resolve(RefreshMode.KeepCurrentValues);}}finally {ctx.SubmitChanges();}
這裡RefreshMode就是表示解決衝突的方法,也有三種:
- KeepChanges 把改變過的屬性值更新到資料庫,沒有改變過的屬性值就用資料庫的當前值
- KeepCurrentValues 把當前所有值更新到資料庫 (用這個好像要好點)
- OverwriteCurrentValues 使用資料庫的當前值,不做強行更新
文章寫的很不錯。 我加了一些個人的語言在裡面。 現在園子裡面LINQ好像不太活躍,大都是一些入門層級的文章。
如果LINQ用到實際項目中時會遇到很多問題, 不知園子裡有沒有一些討論比較深的小組或團隊呢。