在我的服務中,我有一個後臺線程,盡力保存特定實體類型的對象流。代碼大致就是下面的:DB ConnectionState =打開但context.SaveChanges拋出「連接中斷」異常
while (AllowRun)
{
try
{
using (DbContext context = GetNewDbContext())
{
while (AllowRun && context.GetConnection().State == ConnectionState.Open)
{
TEntity entity = null;
try
{
while (pendingLogs.Count > 0)
{
lock (pendingLogs)
{
entity = null;
if (pendingLogs.Count > 0)
{
entity = pendingLogs[0];
pendingLogs.RemoveAt(0);
}
}
if (entity != null)
{
context.Entities.Add(entity);
}
}
context.SaveChanges();
}
catch (Exception e)
{
// (1)
// Log exception and continue execution
}
}
}
}
catch (Exception e)
{
// Log context initialization failure and continue execution
}
}
(這主要是實際的代碼,我省略了幾個試圖保持在內存中彈出的對象,直到我們能夠的東西保存到數據庫時再次異常在被捕獲的非相關部分(1)
block)
所以,本質上,有一個無限循環,試圖從某個列表讀取項目並將其保存到Db。如果我們檢測到與數據庫的連接由於某種原因而失敗,它只是試圖重新打開它並繼續。問題是,有時(我無法弄清楚如何重現它至今),當context.SaveChanges()
被稱爲上面的代碼開始產生以下異常(陷入(1)
塊):
System.Data.EntityException: An error occurred while starting a transaction on the provider connection. See the inner exception for details. --->
System.InvalidOperationException: The requested operation cannot be completed because the connection has been broken.
的誤差記錄,但是當執行返回到context.GetConnection().State == ConnectionState.Open
檢查時,它的計算結果爲true。所以我們處於上下文報告其數據庫連接已打開的狀態,但我們無法針對該上下文運行查詢。重新啓動該服務將消除該問題(以及在調試器中調用AllowRun
變量以強制重新創建上下文)。所以問題是因爲我不能信任上下文的連接狀態,我如何驗證我可以對數據庫運行查詢?
另外,是否有一個乾淨的方法來弄清楚連接不處於「健康」狀態?我的意思是,EntityException
本身不是一個跡象表明我應該重置連接,只有當它的InnerException是InvalidOperationException
與某些特定的消息,那麼是的,現在是時候重置它。但是,現在我猜想在ConnectionState指示一切正常時會出現其他情況,但我無法查詢數據庫。我可以主動地抓住那些人,而不是等到它開始咬我嗎?
你能提供詳細的堆棧跟蹤?似乎是事務搞砸了正在進行的EF連接或遇到連接超時問題(如果分佈式事務正在應用,可能來自MSDTC)。 –
您最有可能忽略的非相關部分確實相關。總而言之,在此操作的整個生命週期內不需要保持連接。您使用連接的唯一方法是SaveChanges調用(通過您重複調用它的方式,如果您的示例即使pendingLogs爲空)。只要在pendingLogs不爲空時創建新的上下文(連接將最常從池中返回)並在SaveChanges後處理(連接將返回到池)。同時檢查您的交易是否升級爲分佈式,以及爲什麼(也許您在一個交易中調用多個數據庫等)。 – Evk
爲什麼你首先得到一個開放連接的上下文? –