Skip to content

Commit fc50d4b

Browse files
committed
Support in sqlserver provider
with code updates from master
1 parent d9ce6a7 commit fc50d4b

File tree

3 files changed

+327
-90
lines changed

3 files changed

+327
-90
lines changed

Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/Connection.cs

Lines changed: 135 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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

Comments
 (0)