diff --git a/Dapper/DynamicParameters.cs b/Dapper/DynamicParameters.cs
index 1feb4d02..a6fc8933 100644
--- a/Dapper/DynamicParameters.cs
+++ b/Dapper/DynamicParameters.cs
@@ -147,6 +147,20 @@ namespace Dapper
AddParameters(command, identity);
}
+ ///
+ /// Add all the parameters needed to the command just before it executes, using the
+ /// command's own text and type for any query-specific handling (literal tokens, etc);
+ /// this allows external tooling (for example build-time code generators) to apply a
+ /// parameter bag without constructing an
+ ///
+ /// The raw command prior to execution
+ public void AddParameters(IDbCommand command)
+ {
+ if (command is null) throw new ArgumentNullException(nameof(command));
+ AddParameters(command, new SqlMapper.Identity(command.CommandText, command.CommandType,
+ command.Connection!, null, GetType()));
+ }
+
///
/// If true, the command-text is inspected and only values that are clearly used are included on the connection
///
diff --git a/Dapper/PublicAPI.Unshipped.txt b/Dapper/PublicAPI.Unshipped.txt
index cf9343cc..a4e055ca 100644
--- a/Dapper/PublicAPI.Unshipped.txt
+++ b/Dapper/PublicAPI.Unshipped.txt
@@ -1,3 +1,4 @@
#nullable enable
static Dapper.SqlMapper.Settings.PreferTypeHandlersForEnums.get -> bool
-static Dapper.SqlMapper.Settings.PreferTypeHandlersForEnums.set -> void
\ No newline at end of file
+static Dapper.SqlMapper.Settings.PreferTypeHandlersForEnums.set -> void
+Dapper.DynamicParameters.AddParameters(System.Data.IDbCommand! command) -> void
diff --git a/tests/Dapper.Tests/ParameterTests.cs b/tests/Dapper.Tests/ParameterTests.cs
index 5eb455c6..5bf0b3ce 100644
--- a/tests/Dapper.Tests/ParameterTests.cs
+++ b/tests/Dapper.Tests/ParameterTests.cs
@@ -928,6 +928,29 @@ namespace Dapper.Tests
Assert.Null(p.Get("@b"));
}
+ [Fact]
+ public void AddParameters_Command_AppliesBagAndLiterals()
+ {
+ // the identity-free overload: external tooling (e.g. build-time code generators)
+ // can apply a bag using the command's own text for query-specific handling
+ using var connection = GetClosedConnection();
+ using var command = connection.CreateCommand();
+ command.CommandText = "select @a + {=b}";
+
+ var args = new DynamicParameters();
+ args.Add("a", 1);
+ args.Add("b", 2);
+ args.AddParameters(command);
+
+ Assert.Equal("select @a + 2", command.CommandText); // literal replaced
+ // (note the literal member is still attached as a parameter too - unused, but
+ // that matches what the bag does under vanilla execution)
+ var p = Assert.IsAssignableFrom(command.Parameters[0]);
+ Assert.Equal("a", p.ParameterName);
+ Assert.Equal(1, p.Value);
+ Assert.Equal(2, command.Parameters.Count);
+ }
+
[Fact]
public void TestAppendingAnonClasses()
{