Skip to content

Commit a7322be

Browse files
author
Nick Craver
committed
Partial fix for #399 - track .Close() where possible
Okay so...we can't fix this completely. It has to be a best effort. The problem here is: not everything is going to call .Close(). The main usage case here is a DbDataReader passed a CommandBehavior.CloseConnection. It will call .Close() *on its expected type*, e.g. a SqlConnection. This will not be triggering the .Close() wrapper introduced here. Everywhere else we do call .Close() explicitly will work fine, but even things like Dapper's .Query() won't show a .Close() in the profiler customer timings if using a data reader with close-on-finish behavior behind the scenes.
1 parent a71fc6b commit a7322be

File tree

2 files changed

+41
-7
lines changed

2 files changed

+41
-7
lines changed

src/MiniProfiler.Shared/Data/ProfiledDbConnection.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,20 @@ public override string ConnectionString
8989
/// Closes the connection to the database.
9090
/// This is the preferred method of closing any open connection.
9191
/// </summary>
92-
public override void Close() => _connection.Close();
92+
public override void Close()
93+
{
94+
var miniProfiler = _profiler as MiniProfiler;
95+
if (miniProfiler == null || !miniProfiler.IsActive || miniProfiler.Options?.TrackConnectionOpenClose == false)
96+
{
97+
_connection.Close();
98+
return;
99+
}
100+
101+
using (miniProfiler.CustomTiming("sql", "Connection Close()", nameof(Close)))
102+
{
103+
_connection.Close();
104+
}
105+
}
93106

94107
/// <summary>
95108
/// Opens a database connection with the settings specified by the <see cref="ConnectionString"/>.
@@ -137,7 +150,7 @@ protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLeve
137150
{
138151
return new ProfiledDbTransaction(_connection.BeginTransaction(isolationLevel), this);
139152
}
140-
153+
141154
/// <summary>
142155
/// Creates and returns a <see cref="DbCommand"/> object associated with the current connection.
143156
/// </summary>

tests/MiniProfiler.Tests/DbProfilerTests.cs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,24 @@ public void TrackingOptions(bool track)
265265
const string cmdString = "Select 1";
266266
GetUnopenedConnection(profiler).Query(cmdString);
267267

268-
CheckConnectionTracking(track, profiler, cmdString, false);
268+
CheckConnectionTracking(track, profiler, cmdString, false, false);
269+
}
270+
271+
[Theory]
272+
[InlineData(true)]
273+
[InlineData(false)]
274+
public void TrackingOptionsExplicitClose(bool track)
275+
{
276+
var options = new MiniProfilerTestOptions { TrackConnectionOpenClose = track };
277+
var profiler = options.StartProfiler("Tracking: " + track);
278+
279+
const string cmdString = "Select 1";
280+
var conn = GetUnopenedConnection(profiler);
281+
conn.Open();
282+
conn.Query(cmdString);
283+
conn.Close();
284+
285+
CheckConnectionTracking(track, profiler, cmdString, false, true);
269286
}
270287

271288
[Theory]
@@ -279,7 +296,7 @@ public async Task TrackingOptionsAsync(bool track)
279296
const string cmdString = "Select 1";
280297
await GetUnopenedConnection(profiler).QueryAsync(cmdString).ConfigureAwait(false);
281298

282-
CheckConnectionTracking(track, profiler, cmdString, true);
299+
CheckConnectionTracking(track, profiler, cmdString, true, true);
283300
}
284301

285302
[Fact]
@@ -292,7 +309,7 @@ public void ShimProfiler()
292309
const string cmdString = "Select 1";
293310
GetUnopenedConnection(currentDbProfiler).Query(cmdString);
294311

295-
CheckConnectionTracking(false, profiler, cmdString, false);
312+
CheckConnectionTracking(false, profiler, cmdString, false, false);
296313
}
297314

298315
private class CurrentDbProfiler : IDbProfiler
@@ -314,7 +331,7 @@ public void OnError(IDbCommand profiledDbCommand, SqlExecuteType executeType, Ex
314331
public void ReaderFinish(IDataReader reader) => GetProfiler()?.ReaderFinish(reader);
315332
}
316333

317-
private void CheckConnectionTracking(bool track, MiniProfiler profiler, string command, bool async)
334+
private void CheckConnectionTracking(bool track, MiniProfiler profiler, string command, bool async, bool expectClose)
318335
{
319336
Assert.NotNull(profiler.Root.CustomTimings);
320337
Assert.Single(profiler.Root.CustomTimings);
@@ -323,9 +340,13 @@ private void CheckConnectionTracking(bool track, MiniProfiler profiler, string c
323340

324341
if (track)
325342
{
326-
Assert.Equal(2, sqlTimings.Count);
343+
Assert.Equal(expectClose ? 3 : 2, sqlTimings.Count);
327344
Assert.Equal(async ? "Connection OpenAsync()" : "Connection Open()", sqlTimings[0].CommandString);
328345
Assert.Equal(command, sqlTimings[1].CommandString);
346+
if (expectClose)
347+
{
348+
Assert.Equal("Connection Close()", sqlTimings[2].CommandString);
349+
}
329350
}
330351
else
331352
{

0 commit comments

Comments
 (0)