Skip to content

Commit e6264b5

Browse files
committed
Add documentation about connection reuse. Fixes #565
1 parent 5880e9e commit e6264b5

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
lastmod: 2018-09-29
3+
date: 2018-09-29
4+
title: Connection Reuse
5+
weight: 10
6+
menu:
7+
main:
8+
parent: troubleshooting
9+
---
10+
11+
# Connection Reuse
12+
13+
A `MySqlConnection` object may only be used for one operation at a time. It may not be shared
14+
across multiple threads and used simultaneously, nor reused on the same thread while there is
15+
an open `MySqlDataReader`.
16+
17+
## Examples of Prohibited Use
18+
19+
### Multiple Threads
20+
21+
You may not execute multiple operations in parallel, for example:
22+
23+
```csharp
24+
using (var connection = new MySqlConnection("..."))
25+
{
26+
await connection.OpenAsync();
27+
await Task.WhenAll( // don't do this
28+
connection.ExecuteAsync("SELECT 1;"),
29+
connection.ExecuteAsync("SELECT 2;"),
30+
connection.ExecuteAsync("SELECT 3;"));
31+
}
32+
```
33+
34+
### Nested Access on Single Thread
35+
36+
You may not reuse the connection when there is an open `MySqlDataReader:`
37+
38+
```csharp
39+
using (var connection = CreateOpenConnection())
40+
using (var command = new MySqlCommand("SELECT id FROM ...", connection))
41+
using (var reader = command.ExecuteReader())
42+
{
43+
while (reader.Read())
44+
{
45+
var idToUpdate = reader.GetValue(0);
46+
connection.Execute("UPDATE ... SET ..."); // don't do this
47+
}
48+
}
49+
```
50+
51+
## How to Fix
52+
53+
For the multithreaded scenario, if concurrent access to the database is truly necessary,
54+
create and open a new `MySqlConnection` on each thread. But in most cases, you should
55+
just write code that sequentially `await`s each asychronous operation (without performing
56+
them in parallel).
57+
58+
59+
For the nested access, read all the values from the `MySqlDataReader` into memory, close
60+
the reader, then process the values. (If the data set is large, you may need to use a batching
61+
approach where you read a limited number of rows in each batch.)

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ public void StartQuerying(MySqlCommand command)
152152
{
153153
m_logArguments[1] = m_state;
154154
Log.Error("Session{0} can't execute new command when in SessionState: {1}: CommandText: {2}", m_logArguments[0], m_state, command.CommandText);
155-
throw new InvalidOperationException("There is already an open DataReader associated with this Connection which must be closed first.");
155+
throw new InvalidOperationException("This MySqlConnection is already in use. See https://fl.vu/mysql-conn-reuse");
156156
}
157157

158158
VerifyState(State.Connected);

0 commit comments

Comments
 (0)