Description:
Under ASP.NET the following errors (among many others) occur if multiple threads try to call MySqlConnection.Open concurrently:
System.ArgumentException: Item has already been added. Key in dictionary: "gb2312" Key being added: "gb2312"
at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
at System.Collections.Hashtable.Add(Object key, Object value)
at MySql.Data.MySqlClient.CharSetMap.LoadCharsetMap()
at MySql.Data.MySqlClient.CharSetMap.GetEncoding(DBVersion version, String CharSetName)
at MySql.Data.MySqlClient.Driver.Configure(MySqlConnection connection)
at MySql.Data.MySqlClient.NativeDriver.Configure(MySqlConnection connection)
at MySql.Data.MySqlClient.MySqlConnection.Open()
MySql.Data.MySqlClient.MySqlException: Character set 'latin1' is not supported
at MySql.Data.MySqlClient.CharSetMap.GetEncoding(DBVersion version, String CharSetName)
at MySql.Data.MySqlClient.Driver.Configure(MySqlConnection connection)
at MySql.Data.MySqlClient.NativeDriver.Configure(MySqlConnection connection)
at MySql.Data.MySqlClient.MySqlConnection.Open()
System.ArgumentException: Item has already been added. Key in dictionary: "latin4" Key being added: "latin4"
at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
at System.Collections.Hashtable.Add(Object key, Object value)
at MySql.Data.MySqlClient.CharSetMap.LoadCharsetMap()
at MySql.Data.MySqlClient.CharSetMap.GetEncoding(DBVersion version, String CharSetName)
at MySql.Data.MySqlClient.Driver.Configure(MySqlConnection connection)
at MySql.Data.MySqlClient.NativeDriver.Configure(MySqlConnection connection)
at MySql.Data.MySqlClient.MySqlConnection.Open()
The problem seems to be in: MySql.Data.MySqlClient.CharSetMap.GetEncoding
if (mapping == null )
InitializeMapping();
How to repeat:
Can only be repeated if multiple threads call MySqlConnection.Open() at the same time.
Suggested fix:
Please move the InitializeMapping call into a static constructor which is guaranteed to be thread safe:
static CharSetMap()
{
InitializeMapping();
}
or (more expensive)
public static Encoding GetEncoding( DBVersion version, string CharSetName )
{
lock(typeof(CharSetMap))
{
if (mapping == null )
InitializeMapping();
}
...
}