Description:
When you add a MySqlParameter to a MySqlParameterCollection (of a MySqlCommand) than remove it than re-add it, MySqlParameterCollection throws an ArgumentException. This situation occurs in a DataBinded Grid depending on use. ArgumentException is like this:
System.ArgumentException was unhandled
Message="Item has already been added. Key in dictionary: '?p1' Key being added: '?p1'"
Source="mscorlib"
StackTrace:
at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
at System.Collections.Hashtable.Add(Object key, Object value)
at MySql.Data.MySqlClient.MySqlParameterCollection.Add(MySqlParameter value)
at WindowsApplication8.Program.Main() in C:\Documents and Settings\Administrator\Belgelerim\Visual Studio 2005\Projects\WindowsApplication8\WindowsApplication8\Program.cs:line 26
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
How to repeat:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
using System.Data;
namespace WindowsApplication8
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
MySqlCommand cmd = new
MySqlCommand("Insert into sometable(s1, s2) values(?p1, ?p2)");
MySqlParameter param1 = cmd.CreateParameter();
param1.ParameterName = "?p1";
param1.DbType = DbType.String;
param1.Value = "Ali Gel";
cmd.Parameters.Add(param1);
cmd.Parameters.RemoveAt(0);
cmd.Parameters.Add(param1);
}
}
}
Suggested fix:
I found the cause and the fix. This exception occurs because when a parameter added to the parametercollection, the parameter also added to the hash and cihash member HashTables but doesn't removed from them when removed from parametercollection. So when you try to re-add that removed parameter, an exception occurs because the item is already in the HashTable. The fix is to remove parameter from HashTables when removed from parametercollection. I provide the fixed versions of three Remove methods below:
public override void Remove(object value)
{
items.Remove(value);
DbParameter p = (DbParameter)value;
hash.Remove(p.ParameterName);
ciHash.Remove(p.ParameterName);
}
public override void RemoveAt(string name)
{
DbParameter p = GetParameter(name);
items.Remove(p);
hash.Remove(p.ParameterName);
ciHash.Remove(p.ParameterName);
}
public override void RemoveAt(int index)
{
DbParameter p = GetParameter(index);
items.RemoveAt(index);
hash.Remove(p.ParameterName);
ciHash.Remove(p.ParameterName);
}