Skip to content

Commit d603d43

Browse files
author
James Crowley
committed
In order to allow re-use of parameters across multiple commands, remove them
from any commands that are created prior to calling Dispose (as that is not sufficient). This will allow use cases where queries are retried (using Polly) for instance, and the parameters are being passed via IDynamicParameters or ICustomQueryParameter
1 parent 80231b4 commit d603d43

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

Dapper.Tests/ParameterTests.cs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace Dapper.Tests
2121
{
2222
public class ParameterTests : TestBase
2323
{
24-
public class DbParams : SqlMapper.IDynamicParameters, IEnumerable<IDbDataParameter>
24+
public class DbDynamicParams : SqlMapper.IDynamicParameters, IEnumerable<IDbDataParameter>
2525
{
2626
private readonly List<IDbDataParameter> parameters = new List<IDbDataParameter>();
2727
public IEnumerator<IDbDataParameter> GetEnumerator() { return parameters.GetEnumerator(); }
@@ -37,6 +37,21 @@ void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Id
3737
command.Parameters.Add(parameter);
3838
}
3939
}
40+
41+
public class DbCustomParam : SqlMapper.ICustomQueryParameter
42+
{
43+
private readonly IDbDataParameter _sqlParameter;
44+
45+
public DbCustomParam(IDbDataParameter sqlParameter)
46+
{
47+
_sqlParameter = sqlParameter;
48+
}
49+
50+
public void AddParameter(IDbCommand command, string name)
51+
{
52+
command.Parameters.Add(_sqlParameter);
53+
}
54+
}
4055

4156
private static List<Microsoft.SqlServer.Server.SqlDataRecord> CreateSqlDataRecordList(IEnumerable<int> numbers)
4257
{
@@ -672,9 +687,9 @@ public class HazSqlHierarchy
672687
#endif
673688

674689
[Fact]
675-
public void TestCustomParameters()
690+
public void TestDynamicParameters()
676691
{
677-
var args = new DbParams {
692+
var args = new DbDynamicParams {
678693
new SqlParameter("foo", 123),
679694
new SqlParameter("bar", "abc")
680695
};
@@ -684,7 +699,53 @@ public void TestCustomParameters()
684699
Assert.Equal(123, foo);
685700
Assert.Equal("abc", bar);
686701
}
702+
703+
[Fact]
704+
public void TestDynamicParametersReuse()
705+
{
706+
var args = new DbDynamicParams {
707+
new SqlParameter("foo", 123),
708+
new SqlParameter("bar", "abc")
709+
};
710+
var result1 = connection.Query("select Foo=@foo, Bar=@bar", args).Single();
711+
var result2 = connection.Query("select Foo=@foo, Bar=@bar", args).Single();
712+
Assert.Equal(123, result1.Foo);
713+
Assert.Equal("abc", result1.Bar);
714+
Assert.Equal(123, result2.Foo);
715+
Assert.Equal("abc", result2.Bar);
716+
}
687717

718+
719+
[Fact]
720+
public void TestCustomParameter()
721+
{
722+
var args = new {
723+
foo = new DbCustomParam(new SqlParameter("foo", 123)),
724+
bar = "abc"
725+
};
726+
var result = connection.Query("select Foo=@foo, Bar=@bar", args).Single();
727+
int foo = result.Foo;
728+
string bar = result.Bar;
729+
Assert.Equal(123, foo);
730+
Assert.Equal("abc", bar);
731+
}
732+
733+
[Fact]
734+
public void TestCustomParameterReuse()
735+
{
736+
var args = new {
737+
foo = new DbCustomParam(new SqlParameter("foo", 123)),
738+
bar = "abc"
739+
};
740+
var result1 = connection.Query("select Foo=@foo, Bar=@bar", args).Single();
741+
var result2 = connection.Query("select Foo=@foo, Bar=@bar", args).Single();
742+
Assert.Equal(123, result1.Foo);
743+
Assert.Equal("abc", result1.Bar);
744+
Assert.Equal(123, result2.Foo);
745+
Assert.Equal("abc", result2.Bar);
746+
}
747+
748+
688749
[Fact]
689750
public void TestDynamicParamNullSupport()
690751
{

Dapper/SqlMapper.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,8 @@ private static GridReader QueryMultipleImpl(this IDbConnection cnn, ref CommandD
10401040
}
10411041
reader.Dispose();
10421042
}
1043+
1044+
cmd?.Parameters.Clear();
10431045
cmd?.Dispose();
10441046
if (wasClosed) cnn.Close();
10451047
throw;
@@ -1127,6 +1129,8 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
11271129
reader.Dispose();
11281130
}
11291131
if (wasClosed) cnn.Close();
1132+
1133+
cmd?.Parameters.Clear();
11301134
cmd?.Dispose();
11311135
}
11321136
}
@@ -1234,6 +1238,7 @@ private static T QueryRowImpl<T>(IDbConnection cnn, Row row, ref CommandDefiniti
12341238
reader.Dispose();
12351239
}
12361240
if (wasClosed) cnn.Close();
1241+
cmd?.Parameters.Clear();
12371242
cmd?.Dispose();
12381243
}
12391244
}
@@ -1458,6 +1463,7 @@ private static IEnumerable<TReturn> MultiMapImpl<TFirst, TSecond, TThird, TFourt
14581463
}
14591464
finally
14601465
{
1466+
ownedCommand?.Parameters.Clear();
14611467
ownedCommand?.Dispose();
14621468
if (wasClosed) cnn.Close();
14631469
}
@@ -1528,6 +1534,7 @@ private static IEnumerable<TReturn> MultiMapImpl<TReturn>(this IDbConnection cnn
15281534
}
15291535
finally
15301536
{
1537+
ownedCommand?.Parameters.Clear();
15311538
ownedCommand?.Dispose();
15321539
if (wasClosed) cnn.Close();
15331540
}
@@ -2831,6 +2838,7 @@ private static int ExecuteCommand(IDbConnection cnn, ref CommandDefinition comma
28312838
finally
28322839
{
28332840
if (wasClosed) cnn.Close();
2841+
cmd?.Parameters.Clear();
28342842
cmd?.Dispose();
28352843
}
28362844
}
@@ -2858,6 +2866,7 @@ private static T ExecuteScalarImpl<T>(IDbConnection cnn, ref CommandDefinition c
28582866
finally
28592867
{
28602868
if (wasClosed) cnn.Close();
2869+
cmd?.Parameters.Clear();
28612870
cmd?.Dispose();
28622871
}
28632872
return Parse<T>(result);
@@ -2881,7 +2890,11 @@ private static IDataReader ExecuteReaderImpl(IDbConnection cnn, ref CommandDefin
28812890
finally
28822891
{
28832892
if (wasClosed) cnn.Close();
2884-
if (cmd != null && disposeCommand) cmd.Dispose();
2893+
if (cmd != null && disposeCommand)
2894+
{
2895+
cmd.Parameters.Clear();
2896+
cmd.Dispose();
2897+
}
28852898
}
28862899
}
28872900

0 commit comments

Comments
 (0)