天天看點

Entity Framework 并發處理

什麼是并發?

并發分悲觀并發和樂觀并發。

悲觀并發:比如有兩個使用者A,B,同時登入系統修改一個文檔,如果A先進入修改,則系統會把該文檔鎖住,B就沒辦法打開了,隻有等A修改完,完全退出的時候B才能進入修改。

樂觀并發:同上面的例子,A,B兩個使用者同時登入,如果A先進入修改緊跟着B也進入了。A修改文檔的同時B也在修改。如果在A儲存之後B再儲存他的修改,此時系統檢測到資料庫中文檔記錄與B剛進入時不一緻,B儲存時會抛出異常,修改失敗。

EF中如何控制并發?

Entity Framework不支援悲觀并發,隻支援樂觀并發。

如果要對某一個表做并發處理,就在該表中加一條Timestamp類型的字段。注意,一張表中隻能有一個Timestamp的字段。

Data Annotations中用Timestamp來辨別設定并發控制字段,辨別為Timestamp的字段必需為byte[]類型。

Entity Framework 并發處理
Entity Framework 并發處理

Fluent API用IsRowVersion方法

我們看到生成的資料庫中,RowVersion是timestamp類型。

Entity Framework 并發處理

下面我們寫一段代碼來測試一下:

Entity Framework 并發處理
Entity Framework 并發處理

上面我們執行個體化了三個DbContext,第一個增加一條記錄到資料庫中,第二個修改剛增加的記錄但不儲存,然後第三個Context也取剛新增的記錄并儲存,最後再儲存第二個Context,結果儲存失敗。

Entity Framework 并發處理

可以看到我們的并發控制取到了作用。

分析EF生成的SQL語句:

可以看到,它在取對應記錄的時候把RowVersion也作為篩選條件。上面例子中的secContext儲存的時候,資料庫中的RowVersion字段的值就變了,是以firContext儲存的時候用原來的RowVersion取值,自然就取不到相應的記錄而報錯。

如果我們隻是要對某個字段作并發控制呢?别着急,EF也有辦法。

Data Annotations中用ConcurrencyCheck來辨別

Entity Framework 并發處理
Entity Framework 并發處理

Fluent API用IsConcurrencyToken方法

上面的實體中,我們将SocialSecurityNumber(社會保險号)辨別為開放式并發,也寫一個類似的代碼測試一下:

Entity Framework 并發處理
Entity Framework 并發處理
Entity Framework 并發處理

運作結果同樣是儲存失敗,說明我們的并發控制起作用了。

分析一下EF執行的SQL:

可以看到,EF将我們要并發控制的列SocialSecurityNumber也作為一個篩選條件,這樣firContext儲存的時候也會因為的資料庫中SocialSecurityNumber值變了,取不到對應的記錄而更新失敗。

 補充一下:如果是EDMX如何将字段設定為Concurrency。很簡單,在對應的字段上右鍵-屬性。在打開的屬性視窗中有一個并發模式,你将它選擇為Fixed即可。

Entity Framework 并發處理

如果我的文章對你有幫助,就點一下推薦吧.(*^__^*)