今天由於併發的問題,又討論了一遍。以前覺得同時兩個線程開啓,線程A加了更新鎖,線程B沒有加,線程A更新後,線程B也會繼續下去代碼。可是今天測試了一下,原來線程A更新後(解鎖),線程B將不會繼續,會出現數據庫語句出現修改之類的提示。sql
寫法 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.事務處理結束(處於事務))線程
接下來有三種狀況:orm
1.1線程A不進行更新操做(沒有update操做,即便沒有改變值),線程A結束事務後(解鎖),線程B將繼續運行blog
1.2線程A進行了更新操做,即此時Status狀態值更改成0,線程B將會跳轉入異常,異常詳細上會有數據庫信息更改之類的提示事務
1.3線程A一直停留在斷點,不進行解鎖操做,時間一旦達到限制,則線程B將會提示請求超時之類的(因爲數據庫請求是有設定時限的)string
2.線程A未進入更新鎖代碼段,則線程B按照正常運行it
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 項。