1- // Copyright (C) 2009-2020 Xtensive LLC.
1+ // Copyright (C) 2009-2021 Xtensive LLC.
22// This code is distributed under MIT license terms.
33// See the License.txt file in the project root for more information.
44// Created by: Denis Krjuchkov
@@ -38,20 +38,35 @@ public override DbParameter CreateParameter()
3838 /// <inheritdoc/>
3939 public override void Open ( )
4040 {
41- if ( ! checkConnectionIsAlive )
41+ if ( ! checkConnectionIsAlive ) {
4242 base . Open ( ) ;
43- else
44- OpenWithCheck ( DefaultCheckConnectionQuery ) ;
43+ }
44+ else {
45+ var connectionHandlers = Extensions . Get < ConnectionHandlersExtension > ( ) ;
46+ if ( connectionHandlers == null ) {
47+ OpenWithCheckFast ( DefaultCheckConnectionQuery ) ;
48+ }
49+ else {
50+ OpenWithCheckAndNotification ( DefaultCheckConnectionQuery , connectionHandlers ) ;
51+ }
52+ }
4553 }
4654
4755 /// <inheritdoc/>
4856 public override Task OpenAsync ( CancellationToken cancellationToken )
4957 {
5058 cancellationToken . ThrowIfCancellationRequested ( ) ;
51- if ( ! checkConnectionIsAlive )
59+ if ( ! checkConnectionIsAlive ) {
5260 return base . OpenAsync ( cancellationToken ) ;
53- else
54- return OpenWithCheckAsync ( DefaultCheckConnectionQuery , cancellationToken ) ;
61+ }
62+
63+ var connectionHandlers = Extensions . Get < ConnectionHandlersExtension > ( ) ;
64+ if ( connectionHandlers == null ) {
65+ return OpenWithCheckFastAsync ( DefaultCheckConnectionQuery , cancellationToken ) ;
66+ }
67+ else {
68+ return OpenWithCheckAndNotificationAsync ( DefaultCheckConnectionQuery , connectionHandlers , cancellationToken ) ;
69+ }
5570 }
5671
5772 /// <inheritdoc/>
@@ -65,7 +80,13 @@ public override void OpenAndInitialize(string initializationScript)
6580 var script = string . IsNullOrEmpty ( initializationScript . Trim ( ) )
6681 ? DefaultCheckConnectionQuery
6782 : initializationScript ;
68- OpenWithCheck ( script ) ;
83+ var connectionHandlers = Extensions . Get < ConnectionHandlersExtension > ( ) ;
84+ if ( connectionHandlers == null ) {
85+ OpenWithCheckFast ( script ) ;
86+ }
87+ else {
88+ OpenWithCheckAndNotification ( script , connectionHandlers ) ;
89+ }
6990 }
7091
7192 /// <inheritdoc/>
@@ -77,7 +98,10 @@ public override Task OpenAndInitializeAsync(string initializationScript, Cancell
7798 var script = string . IsNullOrEmpty ( initializationScript . Trim ( ) )
7899 ? DefaultCheckConnectionQuery
79100 : initializationScript ;
80- return OpenWithCheckAsync ( script , cancellationToken ) ;
101+ var connectionHandlers = Extensions . Get < ConnectionHandlersExtension > ( ) ;
102+ return connectionHandlers == null
103+ ? OpenWithCheckFastAsync ( script , cancellationToken )
104+ : OpenWithCheckAndNotificationAsync ( script , connectionHandlers , cancellationToken ) ;
81105 }
82106
83107 /// <inheritdoc/>
@@ -131,16 +155,16 @@ protected override void ClearActiveTransaction()
131155 activeTransaction = null ;
132156 }
133157
134- private void OpenWithCheck ( string checkQueryString )
158+ private void OpenWithCheckFast ( string checkQueryString )
135159 {
136- bool connectionChecked = false ;
137- bool restoreTriggered = false ;
160+ var connectionChecked = false ;
161+ var restoreTriggered = false ;
138162 while ( ! connectionChecked ) {
139163 base . Open ( ) ;
140164 try {
141165 using ( var command = underlyingConnection . CreateCommand ( ) ) {
142166 command . CommandText = checkQueryString ;
143- command . ExecuteNonQuery ( ) ;
167+ _ = command . ExecuteNonQuery ( ) ;
144168 }
145169 connectionChecked = true ;
146170 }
@@ -160,28 +184,118 @@ private void OpenWithCheck(string checkQueryString)
160184 restoreTriggered = true ;
161185 continue ;
162186 }
163- else
164- throw ;
187+
188+ throw ;
165189 }
166190 }
167191 }
168192
169- private async Task OpenWithCheckAsync ( string checkQueryString , CancellationToken cancellationToken )
193+ private void OpenWithCheckAndNotification ( string checkQueryString , ConnectionHandlersExtension connectionHandlers )
170194 {
171- bool connectionChecked = false ;
172- bool restoreTriggered = false ;
195+ var connectionChecked = false ;
196+ var restoreTriggered = false ;
197+ var handlers = connectionHandlers . Handlers ;
198+ while ( ! connectionChecked ) {
199+ SqlHelper . NotifyConnectionOpening ( handlers , UnderlyingConnection , ( ! connectionChecked && ! restoreTriggered ) ) ;
200+ underlyingConnection . Open ( ) ;
201+ try {
202+ SqlHelper . NotifyConnectionInitializing ( handlers , UnderlyingConnection , checkQueryString , ( ! connectionChecked && ! restoreTriggered ) ) ;
203+ using ( var command = underlyingConnection . CreateCommand ( ) ) {
204+ command . CommandText = checkQueryString ;
205+ _ = command . ExecuteNonQuery ( ) ;
206+ }
207+ connectionChecked = true ;
208+ SqlHelper . NotifyConnectionOpened ( handlers , UnderlyingConnection , ( ! connectionChecked && ! restoreTriggered ) ) ;
209+ }
210+ catch ( Exception exception ) {
211+ SqlHelper . NotifyConnectionOpeningFailed ( handlers , UnderlyingConnection , exception , ( ! connectionChecked && ! restoreTriggered ) ) ;
212+ if ( InternalHelpers . ShouldRetryOn ( exception ) ) {
213+ if ( restoreTriggered ) {
214+ throw ;
215+ }
216+
217+ var newConnection = new SqlServerConnection ( underlyingConnection . ConnectionString ) ;
218+ try {
219+ underlyingConnection . Close ( ) ;
220+ underlyingConnection . Dispose ( ) ;
221+ }
222+ catch { }
223+
224+ underlyingConnection = newConnection ;
225+ restoreTriggered = true ;
226+ continue ;
227+ }
228+
229+ throw ;
230+ }
231+ }
232+ }
233+
234+ private async Task OpenWithCheckFastAsync ( string checkQueryString , CancellationToken cancellationToken )
235+ {
236+ var connectionChecked = false ;
237+ var restoreTriggered = false ;
173238
174239 while ( ! connectionChecked ) {
175240 cancellationToken . ThrowIfCancellationRequested ( ) ;
176241 await base . OpenAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
177242 try {
178243 using ( var command = underlyingConnection . CreateCommand ( ) ) {
179244 command . CommandText = checkQueryString ;
180- await command . ExecuteNonQueryAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
245+ _ = await command . ExecuteNonQueryAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
246+ }
247+ connectionChecked = true ;
248+ }
249+ catch ( Exception exception ) {
250+ if ( InternalHelpers . ShouldRetryOn ( exception ) ) {
251+ if ( restoreTriggered ) {
252+ throw ;
253+ }
254+ var newConnection = new SqlServerConnection ( underlyingConnection . ConnectionString ) ;
255+ try {
256+ underlyingConnection . Close ( ) ;
257+ underlyingConnection . Dispose ( ) ;
258+ }
259+ catch { }
260+
261+ underlyingConnection = newConnection ;
262+ restoreTriggered = true ;
263+ continue ;
264+ }
265+
266+ throw ;
267+ }
268+ }
269+ }
270+
271+ private async Task OpenWithCheckAndNotificationAsync ( string checkQueryString ,
272+ ConnectionHandlersExtension connectionHandlers , CancellationToken cancellationToken )
273+ {
274+ var connectionChecked = false ;
275+ var restoreTriggered = false ;
276+ var handlers = connectionHandlers . Handlers ;
277+
278+ while ( ! connectionChecked ) {
279+ cancellationToken . ThrowIfCancellationRequested ( ) ;
280+
281+ SqlHelper . NotifyConnectionOpening ( handlers , UnderlyingConnection , ! connectionChecked && ! restoreTriggered ) ;
282+
283+ await underlyingConnection . OpenAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
284+ try {
285+ SqlHelper . NotifyConnectionInitializing ( handlers ,
286+ UnderlyingConnection , checkQueryString , ! connectionChecked && ! restoreTriggered ) ;
287+
288+ using ( var command = underlyingConnection . CreateCommand ( ) ) {
289+ command . CommandText = checkQueryString ;
290+ _ = await command . ExecuteNonQueryAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
181291 }
182292 connectionChecked = true ;
293+ SqlHelper . NotifyConnectionOpened ( handlers , UnderlyingConnection , ! connectionChecked && ! restoreTriggered ) ;
183294 }
184295 catch ( Exception exception ) {
296+ SqlHelper . NotifyConnectionOpeningFailed ( handlers ,
297+ UnderlyingConnection , exception , ( ! connectionChecked && ! restoreTriggered ) ) ;
298+
185299 if ( InternalHelpers . ShouldRetryOn ( exception ) ) {
186300 if ( restoreTriggered ) {
187301 throw ;
@@ -197,8 +311,8 @@ private async Task OpenWithCheckAsync(string checkQueryString, CancellationToken
197311 restoreTriggered = true ;
198312 continue ;
199313 }
200- else
201- throw ;
314+
315+ throw ;
202316 }
203317 }
204318 }
0 commit comments