Entity Framework 併發處理

2021-09-07 06:30:32 字數 3751 閱讀 6211

什麼是併發?

併發分悲觀併發和樂觀併發。

悲觀併發:比如有兩個使用者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型別。

public class person

public int socialsecuritynumber

public string firstname

public string lastname

[timestamp]

public byte rowversion

}

fluent api用isrowversion方法

modelbuilder.entity().property(p => p.rowversion).isrowversion();
我們看到生成的資料庫中,rowversion是timestamp型別。

下面我們寫一段**來測試一下:

static void main(string args)

;//新增一條記錄,儲存到資料庫中

using (var con = new breakawaycontext())

var fircontext = new breakawaycontext();

//取第一條記錄,並修改乙個字段:這裡是修改了firstname

//先不儲存

var p1 = fircontext.people.firstordefault();

p1.firstname = "steven";

//再建立乙個context,同樣取第一條記錄,修改lastname欄位並儲存

using (var seccontext = new breakawaycontext())

trycatch (dbupdateconcurrencyexception ex)

console.read();

}

上面我們例項化了三個dbcontext,第乙個增加一條記錄到資料庫中,第二個修改剛增加的記錄但不儲存,然後第三個context也取剛新增的記錄並儲存,最後再儲存第二個context,結果儲存失敗。

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

分析ef生成的sql語句:

exec sp_executesql n'update [dbo].[people]

set [lastname] = @0

where (([personid] = @1) and ([rowversion] = @2))

select [rowversion]

from [dbo].[people]

where @@rowcount > 0 and [personid] = @1',n'@0 nvarchar(max) ,@1 int,@2 binary(8)',@0=n'francis',@1=1,@2=0x00000000000007d1

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

如果我們只是要對某個欄位作併發控制呢?別著急,ef也有辦法。

data annotations中用concurrencycheck來標識

public class person

[concurrencycheck]

public int socialsecuritynumber

public string firstname

public string lastname

public byte rowversion

}

fluent api用isconcurrencytoken方法

modelbuilder.entity().property(p => p.socialsecuritynumber).isconcurrencytoken();
上面的實體中,我們將socialsecuritynumber(社會保險號)標識為開放式併發,也寫乙個類似的**測試一下:

static void main(string args)

;//新增一條記錄,儲存到資料庫中

using (var con = new breakawaycontext())

var fircontext = new breakawaycontext();

//取第一條記錄,並修改socialsecuritynumber欄位

//先不儲存

var p1 = fircontext.people.firstordefault();

p1.socialsecuritynumber = 123;

//再建立乙個context,同樣取第一條記錄,

//修改socialsecuritynumber欄位並儲存

using (var seccontext = new breakawaycontext())

trycatch (dbupdateconcurrencyexception ex)

console.read();

}

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

分析一下ef執行的sql:

exec sp_executesql n'update [dbo].[people]

set [socialsecuritynumber] = @0

where (([personid] = @1) and ([socialsecuritynumber] = @2))

',n'@0 int,@1 int,@2 int',@0=123,@1=1,@2=12345678

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

補充一下:如果是edmx如何將字段設定為concurrency。很簡單,在對應的字段上右鍵-屬性。在開啟的屬性視窗中有乙個併發模式,你將它選擇為fixed即可。

Entity Framework 架構簡介

當微軟的wcf 大行其道,通用資料訪問模型entity framework卻稍遜一籌,有很多需要完善和進步的地方,本文對entity framework 架構做一下簡介。實體框架 entitry framework 以下簡稱ef 看起來像乙個有趣的技術,更強大,比linq to sql 更先進。這兩...

entity framework 批量刪除

以前用sql寫批量刪除的時候,感覺挺利索的,簡潔地寫了 public bool delectusersuggest string addsql 然後在頁面層直接呼叫 現在用entity framework,感覺有點麻煩不能直接delete,還要先把資料查出來,以下是主要 1 先查出實體 region...

Entity Framework 動態查詢

不想多說什麼直接說 region 搜尋並分頁 ljy 傳入搜尋條件,當前頁碼,每頁的顯示的條數,資料的總數 輸出引數 三個引數,返回 商實體 搜尋條件 當前頁碼 每頁的顯示的條數 資料的總數 public iqueryable endregion 在頁面呼叫時如果通過時間來查詢,請記住一定要這樣寫 ...