An Exception at MySqlPoolManager.GetPoolAsync
Posted by: Tee Loffee
Date: July 06, 2023 01:38AM

When i use this package,it occasionally threw the following exception during startup:


An item with the same key has already been added. Key: database=;server=;user id=;password=;characterset=;pooling=True;allowzerodatetime=True at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at MySql.Data.MySqlClient.MySqlPoolManager.GetPoolAsync(MySqlConnectionStringBuilder settings, Boolean execAsync, CancellationToken cancellationToken) at MySql.Data.MySqlClient.MySqlConnection.OpenAsync(Boolean execAsync, CancellationToken cancellationToken) at MySql.Data.MySqlClient.MySqlConnection.Open() at


I think this exception is caused by multi-threading,and you can reporduce it with the following code:

```C#
var connStr = "Initial Catalog=***;Data Source='***';User Id='***';Password='***';charset='utf8mb4';pooling=true;Allow Zero Datetime=True;";
Parallel.For(0, 10, (i) =>
{
try
{
using (var conn = new MySqlConnection(connStr))
{
conn.Open();

}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
});
```

After reading the source code,I believe that this bug is casused by MySqlPoolManager incorrectly using SemaphoreSlim:

```C#
public static async Task<MySqlPool> GetPoolAsync(MySqlConnectionStringBuilder settings, bool execAsync, CancellationToken cancellationToken)
{
string text = GetKey(settings);
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1);
semaphoreSlim.Wait(CancellationToken.None);
Pools.TryGetValue(text, out var value);
if (value == null)
{
value = await MySqlPool.CreateMySqlPoolAsync(settings, execAsync, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
Pools.Add(text, value);
}
else
{
value.Settings = settings;
}

semaphoreSlim.Release();
return value;
}
```

I think the correct way to do it shoule be like this:
```
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1);
public static async Task<MySqlPool> GetPoolAsync(MySqlConnectionStringBuilder settings, bool execAsync, CancellationToken cancellationToken)
{
string text = GetKey(settings);

semaphoreSlim.Wait(CancellationToken.None);
Pools.TryGetValue(text, out var value);
if (value == null)
{
value = await MySqlPool.CreateMySqlPoolAsync(settings, execAsync, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
Pools.Add(text, value);
}
else
{
value.Settings = settings;
}

semaphoreSlim.Release();
return value;
}
```

Options: ReplyQuote


Subject
Written By
Posted
An Exception at MySqlPoolManager.GetPoolAsync
July 06, 2023 01:38AM


Sorry, you can't reply to this topic. It has been closed.

Content reproduced on this site is the property of the respective copyright holders. It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.