Skip to content

Commit 73532d9

Browse files
committed
Track parameter name changes. Fixes #811
1 parent 86c225d commit 73532d9

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

src/MySqlConnector/MySql.Data.MySqlClient/MySqlParameter.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ public override string ParameterName
121121
set
122122
{
123123
m_name = value ?? "";
124-
NormalizedParameterName = value is null ? "" : NormalizeParameterName(m_name);
124+
var newNormalizedParameterName = value is null ? "" : NormalizeParameterName(m_name);
125+
ParameterCollection?.ChangeParameterName(this, NormalizedParameterName, newNormalizedParameterName);
126+
NormalizedParameterName = newNormalizedParameterName;
125127
}
126128
}
127129

@@ -205,6 +207,8 @@ private MySqlParameter(MySqlParameter other, string parameterName)
205207

206208
internal string NormalizedParameterName { get; private set; }
207209

210+
internal MySqlParameterCollection? ParameterCollection { get; set; }
211+
208212
internal void AppendSqlString(ByteBufferWriter writer, StatementPreparerOptions options)
209213
{
210214
var noBackslashEscapes = (options & StatementPreparerOptions.NoBackslashEscapes) == StatementPreparerOptions.NoBackslashEscapes;

src/MySqlConnector/MySql.Data.MySqlClient/MySqlParameterCollection.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public MySqlParameter AddWithValue(string parameterName, object? value)
6868

6969
public override void Clear()
7070
{
71+
foreach (var parameter in m_parameters)
72+
parameter.ParameterCollection = null;
7173
m_parameters.Clear();
7274
m_nameToIndex.Clear();
7375
}
@@ -113,6 +115,7 @@ public override void RemoveAt(int index)
113115
var oldParameter = m_parameters[index];
114116
if (oldParameter.NormalizedParameterName is object)
115117
m_nameToIndex.Remove(oldParameter.NormalizedParameterName);
118+
oldParameter.ParameterCollection = null;
116119
m_parameters.RemoveAt(index);
117120

118121
foreach (var pair in m_nameToIndex.ToList())
@@ -130,9 +133,11 @@ protected override void SetParameter(int index, DbParameter value)
130133
var oldParameter = m_parameters[index];
131134
if (oldParameter.NormalizedParameterName is object)
132135
m_nameToIndex.Remove(oldParameter.NormalizedParameterName);
136+
oldParameter.ParameterCollection = null;
133137
m_parameters[index] = newParameter;
134138
if (newParameter.NormalizedParameterName is object)
135139
m_nameToIndex.Add(newParameter.NormalizedParameterName, index);
140+
newParameter.ParameterCollection = this;
136141
}
137142

138143
protected override void SetParameter(string parameterName, DbParameter value) => SetParameter(IndexOf(parameterName), value);
@@ -153,13 +158,29 @@ protected override void SetParameter(int index, DbParameter value)
153158
set => SetParameter(name, value);
154159
}
155160

161+
internal void ChangeParameterName(MySqlParameter parameter, string oldName, string newName)
162+
{
163+
if (m_nameToIndex.TryGetValue(oldName, out var index) && m_parameters[index] == parameter)
164+
m_nameToIndex.Remove(oldName);
165+
else
166+
index = m_parameters.IndexOf(parameter);
167+
168+
if (newName.Length != 0)
169+
{
170+
if (m_nameToIndex.ContainsKey(newName))
171+
throw new MySqlException(@"There is already a parameter with the name '{0}' in this collection.".FormatInvariant(parameter.ParameterName));
172+
m_nameToIndex[newName] = index;
173+
}
174+
}
175+
156176
private void AddParameter(MySqlParameter parameter)
157177
{
158178
if (!string.IsNullOrEmpty(parameter.NormalizedParameterName) && NormalizedIndexOf(parameter.NormalizedParameterName) != -1)
159179
throw new MySqlException(@"Parameter '{0}' has already been defined.".FormatInvariant(parameter.ParameterName));
160180
m_parameters.Add(parameter);
161181
if (!string.IsNullOrEmpty(parameter.NormalizedParameterName))
162182
m_nameToIndex[parameter.NormalizedParameterName] = m_parameters.Count - 1;
183+
parameter.ParameterCollection = this;
163184
}
164185

165186
readonly List<MySqlParameter> m_parameters;

tests/SideBySide/ParameterCollection.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,53 @@ public void CopyToIndexOutOfRange()
257257
Assert.Throws<ArgumentException>(() => m_parameterCollection.CopyTo(new DbParameter[2], 3));
258258
}
259259

260+
[Fact]
261+
public void ChangeParameterNameAfterAdd()
262+
{
263+
using var cmd = new MySqlCommand();
264+
using var cmd2 = new MySqlCommand();
265+
var parameter = cmd.CreateParameter();
266+
parameter.ParameterName = "@a";
267+
268+
cmd2.Parameters.Add(parameter);
269+
cmd.Parameters.Add(parameter);
270+
271+
parameter.ParameterName = "@b";
272+
273+
Assert.Equal(parameter, cmd.Parameters["@b"]);
274+
Assert.Throws<ArgumentException>(() => cmd.Parameters["@a"]);
275+
276+
// only works for the last collection that contained the parameter
277+
Assert.Throws<ArgumentException>(() => cmd2.Parameters["@b"]);
278+
Assert.Equal(parameter, cmd2.Parameters["@a"]);
279+
}
280+
281+
[Fact]
282+
public void SetParameterNameAfterAdd()
283+
{
284+
using var cmd = new MySqlCommand();
285+
var parameter = cmd.CreateParameter();
286+
cmd.Parameters.Add(parameter);
287+
parameter.ParameterName = "@a";
288+
Assert.Equal(parameter, cmd.Parameters["@a"]);
289+
}
290+
291+
[Fact]
292+
public void SetTwoParametersToSameNAme()
293+
{
294+
using var cmd = new MySqlCommand();
295+
var parameter1 = cmd.CreateParameter();
296+
cmd.Parameters.Add(parameter1);
297+
var parameter2 = cmd.CreateParameter();
298+
cmd.Parameters.Add(parameter2);
299+
parameter1.ParameterName = "@a";
300+
#if !BASELINE
301+
Assert.Throws<MySqlException>(() => parameter2.ParameterName = "@a");
302+
#else
303+
Assert.Throws<ArgumentException>(() => parameter2.ParameterName = "@a");
304+
#endif
305+
}
306+
260307
MySqlCommand m_command;
261308
MySqlParameterCollection m_parameterCollection;
262309
}

0 commit comments

Comments
 (0)