Skip to content

Commit 4a61afd

Browse files
committed
Fix exception in Dispose. Fixes #383
MySqlTransaction.Dispose should be a no-op if the underlying connection is already closed.
1 parent a6ab560 commit 4a61afd

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

src/MySqlConnector/MySqlClient/MySqlTransaction.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
using System;
1+
using System;
22
using System.Data;
33
using System.Data.Common;
44
using System.Threading;
55
using System.Threading.Tasks;
66
using MySql.Data.Protocol.Serialization;
7-
using MySql.Data.Serialization;
87

98
namespace MySql.Data.MySqlClient
109
{
@@ -77,10 +76,13 @@ protected override void Dispose(bool disposing)
7776
{
7877
if (disposing)
7978
{
80-
if (!m_isFinished && m_connection != null && m_connection.CurrentTransaction == this)
79+
if (!m_isFinished && m_connection?.CurrentTransaction == this)
8180
{
82-
using (var cmd = new MySqlCommand("rollback", m_connection, this))
83-
cmd.ExecuteNonQuery();
81+
if (m_connection.Session.IsConnected)
82+
{
83+
using (var cmd = new MySqlCommand("rollback", m_connection, this))
84+
cmd.ExecuteNonQuery();
85+
}
8486
m_connection.CurrentTransaction = null;
8587
}
8688
m_connection = null;

tests/SideBySide/CommandTimeoutTests.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,71 @@ public async Task CommandTimeoutResetsOnReadAsync()
250250
Assert.Equal(ConnectionState.Open, m_connection.State);
251251
}
252252

253+
254+
[Fact]
255+
public void TransactionCommandTimeoutWithSleepSync()
256+
{
257+
using (var transaction = m_connection.BeginTransaction())
258+
using (var cmd = new MySqlCommand("SELECT SLEEP(120);", m_connection, transaction))
259+
{
260+
cmd.CommandTimeout = 2;
261+
var sw = Stopwatch.StartNew();
262+
try
263+
{
264+
using (var reader = cmd.ExecuteReader())
265+
{
266+
// shouldn't get here
267+
Assert.True(false);
268+
}
269+
}
270+
catch (MySqlException ex)
271+
{
272+
sw.Stop();
273+
Assert.Contains("timeout", ex.Message, StringComparison.OrdinalIgnoreCase);
274+
#if !BASELINE
275+
// https://bugs.mysql.com/bug.php?id=86009
276+
TestUtilities.AssertDuration(sw, cmd.CommandTimeout * 1000 - 100, 500);
277+
#endif
278+
}
279+
}
280+
281+
#if !BASELINE
282+
Assert.Equal(ConnectionState.Closed, m_connection.State);
283+
#endif
284+
}
285+
286+
[Fact]
287+
public async Task TransactionCommandTimeoutWithSleepAsync()
288+
{
289+
using (var transaction = await m_connection.BeginTransactionAsync())
290+
using (var cmd = new MySqlCommand("SELECT SLEEP(120);", m_connection, transaction))
291+
{
292+
cmd.CommandTimeout = 2;
293+
var sw = Stopwatch.StartNew();
294+
try
295+
{
296+
using (var reader = await cmd.ExecuteReaderAsync())
297+
{
298+
// shouldn't get here
299+
Assert.True(false);
300+
}
301+
}
302+
catch (MySqlException ex)
303+
{
304+
sw.Stop();
305+
Assert.Contains("timeout", ex.Message, StringComparison.OrdinalIgnoreCase);
306+
#if !BASELINE
307+
// https://bugs.mysql.com/bug.php?id=86009
308+
TestUtilities.AssertDuration(sw, cmd.CommandTimeout * 1000 - 100, 500);
309+
#endif
310+
}
311+
}
312+
313+
#if !BASELINE
314+
Assert.Equal(ConnectionState.Closed, m_connection.State);
315+
#endif
316+
}
317+
253318
readonly DatabaseFixture m_database;
254319
readonly MySqlConnection m_connection;
255320
}

0 commit comments

Comments
 (0)