2016-11-15 387 views
1

我工作的一個非常大的項目,這是應該跟一個很老的指揮基地API,並進行大量的行動,他們每個人都必須執行許多命令來獲得到了這一點,然後我必須保存結果的狀態。如何避免的DbContext問題在多線程方案

大家會談到我的數據庫,他們添加一條記錄到我的進程隊列,我讀它,執行一些動作,返回無論是在排隊的過程本身或受人尊敬的表中的一些結果。

主管道如下圖所示,我省略了很多動作和鎖。 enter code here

DB是EF DbContext,黑盒子,是在主線程中運行的動作,它運行多個動作並反覆執行,直到應用程序終止。

橙盒,是子線程誰執行的操作後,他們被主線程調用。

以前我有1個問題,數據庫由於事務而死亡,但是因爲必須在我的隊列中有1個API或者至多2個,我只覺得它在SQL管理工具下,所以我想稍後修復它。

,但新的,我覺得這個問題一段時間了,但今天我看到了,......我有一個失敗的動作,然後應用程序開始重複同樣的過程,一遍又一遍,而不終止它或做任何其他,但它應該返回成功或錯誤。所以我跟蹤了一會兒,我注意到它是失敗的地方(內部異常處理程序之一),它說我試圖插入一個重複的密鑰到數據庫中,所以我去看看Db的變化,我注意到我有超過五個條目,這應該只有一個。

,所以我首先想到的每一個dB.SaveChange之前得到改變乘坐的,所以我就在網上找到了一些代碼段這使得所有的變化保持不變。 所以我開始改變我的應用程序添加這段代碼:

lock(DbAction){ 
    ClearingDbContextChanges(); 
    AddResults() if there is any 
    Change() if there is any 
    Delete() if there is any 
    SetEntity as Modified if there is any 
    Db.SaveChanges() 
} 

然後之前,我跑我到達最後一個景點,在那裏我發現我不能再使用此應用程序的運行,並呈現一些我的主要行動無法使用。

+0

「如何避免多線程場景中的DbContext問題」>不要重複使用來自多個線程的相同DbContext - 每次需要時創建新的DbContext。 – Evk

+0

當數據庫對它們進行事務鎖定時,訪問相同數據會不會導致更多的麻煩? – deadManN

+2

我會說它永遠不會創建更多的問題,從多個線程重用相同的DbContext - 這是一個真正的禁忌。 – Evk

回答

0
lock(DbAction) { 
    // Modify DB 
} 

混合應用程序鎖和DB鎖。你正在尋求一個無法察覺的僵局。鎖定等待鏈有周期時發生死鎖。數據庫能夠檢測這些週期並解決死鎖(通過選擇受害者並中止其事務)。但是,當您像應用程序鎖和數據庫鎖一樣組合時,等待鏈可以通過應用程序鎖形成一個循環。認爲線程A持有數據庫鎖1並等待DbAction,線程2持有DbAction並等待數據庫鎖1.這些死鎖鏈是由DB無法檢測到的,因此沒有發生死鎖。你的應用程序將永遠保持僵局(直到明確殺死)。

同時保持應用程序lock不要發出DB電話。決不。永遠。

現在,針對您的問題:您展示典型的ACID不一致問題。您的工作單元似乎反覆執行(數據庫中的重複條目)和/或在數據庫中保存不一致的狀態(缺少事務處理範圍?)。人們無法猜測那裏有什麼問題。

+0

好吧,我不想鎖定數據庫,我希望它被解鎖,但我需要交易繼續下去,如果某件事失敗了,這個項目是那些炸燬的那個,所以我需要定義它們。我介紹Locks不是爲了控制數據庫,我想,但是你恢復了那部分。我只用它們來管理,哪些池項目應該通過並跟蹤活動/非活動會話。也跟蹤隊列項目,完全可以說我管理我的處理流程,並且整個大約1年我在這個系統上工作,我似乎沒有造成任何死角。 – deadManN

+0

嗯,我仍然沒有在同一時間啓動如此多的池對象和請求,因爲它是所有的測試和調試,但我認爲我的系統沒有太多的bug,我比那更害怕RCW異常,因爲API只能在Windows窗體上運行,並且它應該是同步的,我以某種方式將它拿出來交易,但仍然無法處理。 – deadManN