今天因為並發的問題,又討論了一遍。之前以為同時兩個線程開啟,線程A加了更新鎖,線程B沒有加,線程A更新后,線程B也會繼續下去代碼。但是今天測試了一下,原來線程A更新后(解鎖),線程B將不會繼續,會出現數據庫語句出現修改之類的提示。
寫法 SELECT * FROM TABLE WITH UPDLOCK WHERE ID=1
A代碼段示例:
using (TransactionScope trans = new TransactionScope())
{
using (var dbContext = new Qxun.Activity.DAL.ActivityDbContext())
{
string sqlStr = string.Format("SELECT * FROM TABLE WITH(UPDLOCK) WHERE ID={0} ", crossDomainPayRecord.ID);
VIPWeRegister046Play model = dbContext.Database.SqlQuery<VIPWeRegister046Play>(sqlStr).FirstOrDefault();
if (Status == 0)//說明出現問題
{
model.Status = Status;
dbContext.Update<TABLE>(model);
trans.Complete();
return Content(res.ToXml());
}
trans.Complete();
}
}
B代碼段示例 :
using (ActivityDbContext dbContext=new ActivityDbContext())
{
List<TABLE> model= dbContext.TABLE.ToList();
foreach (var item in model)
{
item.Status= 2;
dbContext.Insert<Table>(new Table());
dbContext.Update<TABLE>(item);
}
List<Share> share = dbContext.Shares.ToList();
if (share.Count == 0)
{
dbContext.Insert<Share>(new Share());
}
share = dbContext.Shares.ToList();
foreach (var item in share)
{
item.MerchantWeixinUserID = 1;
dbContext.Update<Share>(item);
}
}
1.線程A進入更新鎖代碼段,線程B將會停止在dbContext.Update處,不會再繼續下去(解鎖操作兩種:1.更新操作(非事務處理);2.事務處理結束(處於事務))
接下來有三種情況:
1.1線程A不進行更新操作(沒有update操作,即使沒有改變值),線程A結束事務后(解鎖),線程B將繼續運行
1.2線程A進行了更新操作,即此時Status狀態值更改為0,線程B將會跳轉入異常,異常詳細上會有數據庫信息更改之類的提示
1.3線程A一直停留在斷點,不進行解鎖操作,時間一旦達到限制,則線程B將會提示請求超時之類的(由於數據庫請求是有設定時限的)
2.線程A未進入更新鎖代碼段,則線程B按照正常運行
3.線程A進入更新鎖代碼段時,線程B也可以使用select獲取,即List<TABLE> model= dbContext.TABLE.ToList();這句會被執行的,直到update操作停止
4.一旦A線程進入更新鎖代碼,且進行了update操作,線程B中的插入更新dbContext.Insert<Table>(new Table()); dbContext.Update<TABLE>(item);這兩句都不能執行,會出現報錯。而share表相關的insert和update也不能運行,這是因為share的代碼處理在TABLE下面,此時dbContext已是異常狀態。如果將share放置到TABLE代碼上方,則會正常運行或者是將share重新開啟一個dbContext2進行操作。不過其中應該還有一些緣由...
5.一旦A線程進入更新鎖代碼,且未進行update操作,線程B中的插入dbContext.Insert<Table>(new Table());代碼是會被執行的,且share相關的代碼都會被執行。
異常提示:存儲區更新、插入或刪除語句影響到了意外的行數(0)。實體在加載后可能被修改或刪除。刷新 ObjectStateManager 項。
