EF6學習筆記二十六:連接彈性
要專業系統地學習EF推薦《你必須掌握的Entity Framework 6.x與Core 2.0》。這本書作者(汪鵬,Jeffcky)的博客:https://www.cnblogs.com/CreateMyself/
連接彈性這一節,作者說的不是很多,而且又出現一個polly庫,感覺弄下去真的要花不少時間。
這一塊我目前沒有準備繼續去弄,也就簡單記錄一下我從這一節內容中學到的東西吧。
連接彈性,什麽意思呢?就是你數據庫的連接要是斷開了,那麽還有其他的機制還對這一情況做處理。如果說連接一斷就隨他去了,顯然不夠有“彈性”。
說到這一點我想到了我在學習node.js時用到的一個啟動器,叫forever,當然啟動器也有很多種。什麽意思呢?如果說你的服務跑起來了,不用啟動器的情況,一個小的錯誤就能造成你服務關閉。那麽我用啟動器來啟動我的項目就不會出來這種情況。
一般很多部署node程序會用到pm2,這個也差不多就是這種功能,它有一個守護進程,讓你的網站不至於一個錯誤就停止了。
所以我就弄不懂IIS中怎麽就沒聽說過有什麽啟動器。node裏面學的東西其實沒多少,就是使用各種包,也不用去管具體實現。有點沒勁。最有用的就是它和.net程序之間的差異能夠讓人引發很多思考。
說回EF中連接彈性的問題。其實如果說數據庫連接斷開了,可能會有很多種情況,可能因為是網絡問題啊。那麽我們能夠想到的應對方法就是去重試。
EF提供了大量有關暫時異常的信息。如果由於任何原因與數據源的連接丟失並且未達到重試限制,那麽它將會以和禁用連接彈性相同的方式引發異常。
EF6.X上給與了一下4種連接策略
1.DefaultExceptionStrategy:默認執行策略,當失敗時,對除SQL Server 以外的數據庫不會進行重試。
2.DefaultSqlExecutionStrategy:根本不會重試,但是會包含任何可能的短暫異常,以通知開發者可能需要啟用連接彈性,次類受保護限制。
3.DbExecutionStrategy:此類適用於其他執行策略的基類,以指數實現重試策略,其中初始重試以0計數,並且延遲指數增加,知道命中最大重試計數。次類具有抽象的ShouldRetryOn方法,可以在派生執行策略中實現,以控制應重試哪些異常。
4.SqlAzureExecutionStrategy:該執行策略繼承自DbExecutionStrategy,並將重試在使用SqlAzure時可能一直出現的異常。
上面的是書中的原話,我還是得用自己的話說一下,數據源連接丟失,EF默認是有重試的。但是我按照書上的代碼寫出來,有一些疑問。
來看一下寫一個派生自DbExecutionStrategy,首先我了解到,數據庫連接丟失,EF會調用哪個方法,那就知道了有這個切入點吧.
ShouldRetryOn方法中我只是加了一句console,還是執行的基類的代碼
public class SqlServerExecutionStrategy : DbExecutionStrategy { public SqlServerExecutionStrategy() { } /// <summary> /// 確定指定的異常是否表示臨時故障 如果指定的異常被認為是暫時的,則為true,否則為false。 /// </summary> /// <param name="maxRetryCount">最大重試次數</param> /// <param name="maxDelay">最大等待時長</param> public SqlServerExecutionStrategy(int maxRetryCount, TimeSpan maxDelay) : base(maxRetryCount, maxDelay) { } protected override bool ShouldRetryOn(Exception exception) { // 同樣的是打印四次 Console.WriteLine("777777777777777777777777777"); throw new NotImplementedException(); } }View Code
寫一個派生自DbConfiguration的類,在EF中註冊配置。
public class EFConfiguration : DbConfiguration { public EFConfiguration() { SetExecutionStrategy(SqlProviderServices.ProviderInvariantName, () => new SqlServerExecutionStrategy(3, TimeSpan.FromSeconds(5))); } }View Code
然後我關閉sqlserver服務,這樣它將連接不到數據庫
可以看到打印了4次,那意思是重試連接了4次嗎?
在EFConfiguration傳遞的3和5,意思是重試次數為3次,最大延遲時間為5秒,那麽我改成重試1次,還是一樣,這個方法被調用4次。所以我就懷疑這是不是有問題?
如果開啟sqlserver服務,這個方法一次都不會被調用
途中我碰到一個問題,就是我的sqlsever服務斷開之後,運行程序,控制臺過了很久才出現內容,為什麽等待了那麽久?我突然想到連接字符串裏面有個Connect Timeout屬性,默認是30秒.於是我改成5秒,發現確實是這裏的問題。
接著來看作者在shouldRetryOn方法中寫的代碼,我加了三句console
protected override bool ShouldRetryOn(Exception exception) { Console.WriteLine("11111111111111111111111111111111111111111"); bool bRetry = false; if (exception is SqlException objSqlException) { Console.WriteLine("222222222222222222222222222222222"); var lstErrorNumbersToRetry = new List<int>() { 5 }; if (objSqlException.Errors.Cast<SqlError>().Any(a => lstErrorNumbersToRetry.Contains(a.Number))) { Console.WriteLine("33333333333333333333333333333"); bRetry = true; } } return bRetry; }View Code
同樣關閉Sqlserver服務來執行看一下
shouldRetryOn這個方法返回的是bool類型,如果異常是短暫的返回true,否則false,剛剛的打印內容可以看到這個異常被認為不是暫時的。
作者的判斷依據是"5"這個數字,但是5代表的是什麽呢?
轉到Number定義看一下
通過這幾句註釋完全看不到什麽有價值的東西。
幸好.net開源了,那就去MSDN上看一下:https://docs.microsoft.com/zh-cn/dotnet/api/system.data.sqlclient.sqlerror.number?view=netframework-4.7.2#System_Data_SqlClient_SqlError_Number
它說SqlError.Number類型的值對應master.dbo.sysmessages表,那就去查表吧
但是根本就沒有5啊,最小都是21,。我其實也把異常裏面的Number看了一下,發現是2
protected override bool ShouldRetryOn(Exception exception) { Console.WriteLine("11111111111111111111111111111111111111111"); bool bRetry = false; if (exception is SqlException objSqlException) { Console.WriteLine("222222222222222222222222222222222"); var lstErrorNumbersToRetry = new List<int>() { 5 }; var abc = objSqlException.Errors.Cast<SqlError>(); var str = ""; foreach (var item in abc) { str += item.Number + ","; } var str2 = str; // 2, if (objSqlException.Errors.Cast<SqlError>().Any(a => lstErrorNumbersToRetry.Contains(a.Number))) { Console.WriteLine("33333333333333333333333333333"); bRetry = true; } } return bRetry; }View Code
行,到此為止,這個對我來說已經進行不下去了。
總結一下我通過寫一個派生自DbExecutionStrategy類有什麽作用呢?作用就是知道數據庫連接丟失,shouldRetryOn方法會被調用,這一點是肯定的,那麽其他的東西不怎麽明白也就不妄下結論了
這就是簡單的連接彈性。現在來說道Polly庫。
這個是做什麽的呢?其實我覺得就是對異常處理做出的一種規範。
數據庫連接斷開,只有重試吧?原因有很多種,很有可能他就一直斷開了。所以Polly他為你是解決不了的。你說你自己都不知道發生什麽問題,polly又能怎麽辦。
我剛開始就是認為,用這個那一定是不管什麽情況下的連接丟失,polly都能幫我解決,這就不對了。
我覺得Polly就是提供了對異常處理的規範,它有很多種策略,可以參考Jeffcky的一篇博客:https://www.cnblogs.com/CreateMyself/p/7589397.html
行吧,就這了。我開始想把polly那些東西再寫一下的。不過想到也沒有太了解,也就沒有耐心了。
EF6學習筆記二十六:連接彈性