什麼是併發?
併發分悲觀併發和樂觀併發。
悲觀併發:比如有兩個使用者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型別。
publicfluent api用isrowversion方法class
person
public
int socialsecuritynumber
public
string firstname
public
string lastname
[timestamp]
public
byte rowversion
}
modelbuilder.entity().property(p => p.rowversion).isrowversion();我們看到生成的資料庫中,rowversion是timestamp型別。
下面我們寫一段**來測試一下:
static上面我們例項化了三個dbcontext,第乙個增加一條記錄到資料庫中,第二個修改剛增加的記錄但不儲存,然後第三個context也取剛新增的記錄並儲存,最後再儲存第二個context,結果儲存失敗。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())
try
catch
(dbupdateconcurrencyexception ex)
console.read();
}
可以看到我們的併發控制取到了作用。
分析ef生成的sql語句:
exec sp_executesql n'可以看到,它在取對應記錄的時候把rowversion也作為篩選條件。上面例子中的seccontext儲存的時候,資料庫中的rowversion欄位的值就變了,所以fircontext儲存的時候用原來的rowversion取值,自然就取不到相應的記錄而報錯。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
如果我們只是要對某個欄位作併發控制呢?別著急,ef也有辦法。
data annotations中用concurrencycheck來標識
publicfluent api用isconcurrencytoken方法class person
[concurrencycheck
]public
int socialsecuritynumber
public string firstname
public string lastname
public byte rowversion
}
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())
try
catch
(dbupdateconcurrencyexception ex)
console.read();
}
分析一下ef執行的sql:
exec sp_executesql n'可以看到,ef將我們要併發控制的列socialsecuritynumber也作為乙個篩選條件,這樣fircontext儲存的時候也會因為的資料庫中socialsecuritynumber值變了,取不到對應的記錄而更新失敗。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
補充一下:如果是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 在頁面呼叫時如果通過時間來查詢,請記住一定要這樣寫 ...