Passing Output parameters to stored procedure using dapper in c# code
Solution 1
Just searching the Test.cs file you could find this example
public void TestProcSupport()
{
var p = new DynamicParameters();
p.Add("a", 11);
p.Add("b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
connection.Execute(@"create proc #TestProc
@a int,
@b int output
as
begin
set @b = 999
select 1111
return @a
end");
connection.Query<int>("#TestProc", p, commandType: CommandType.StoredProcedure).First().IsEqualTo(1111);
p.Get<int>("c").IsEqualTo(11);
p.Get<int>("b").IsEqualTo(999);
}
So, I suppose that your C# code could be written as
public void InsertData()
{
var p = new DynamicParameters();
p.Add("VAR1", "John");
p.Add("VAR2", "McEnroe");
p.Add("BASEID", 1);
p.Add("NEWID", dbType: DbType.Int32, direction: ParameterDirection.Output);
connection.Query<int>("SP_MYTESTpROC", p, commandType: CommandType.StoredProcedure);
int newID = p.Get<int>("NEWID");
}
As a side note, do not use SP as prefix for your stored procedure. It is reserved for system defined procedures and you could find yourself in troubles if Microsoft decides to use the same name. Albeit improbable it is a bad practice and why risk?
Solution 2
Further to "ath's" suggestion: To avoid reflection, DynamicParmers.AddDynamicParams() takes an anonymous object, after which you could add the return paramter like this...
var param = new { A="a", B="b" };
var dynamicParameters = new DynamicParameters();
dynamicParameters.AddDynamicParams(parameters);
dynamicParameters.Add("return", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
now use the dynamicParameters object in your dapper call instead of the anonymous param object.
(You can also do this for an output parameter if preferred)
Solution 3
If you always have an OUTPUT parameter of INTEGER type named @id
(@id = @id OUTPUT
), you could make an extension method like this which would allow you to use the regular Dapper
syntax passing the sql string and an anonymous
object:
using Dapper;
using System.Data;
using System.Data.SqlClient;
public static int ExecuteOutputParam
(this IDbConnection conn, string sql, object args)
{
// Stored procedures with output parameter require
// dynamic params. This assumes the OUTPUT parameter in the
// SQL is an INTEGER named @id.
var p = new DynamicParameters();
p.Add("id", dbType: DbType.Int32, direction: ParameterDirection.Output);
var properties = args.GetType().GetProperties();
foreach (var prop in properties)
{
var key = prop.Name;
var value = prop.GetValue(args);
p.Add(key, value);
}
conn.Execute(sql, p);
int id = p.Get<int>("id");
return id;
}
This uses reflection to read all properties, but if you can take that penalty, you don't have to boilerplate the DynamicParameters
for every call.
For transactions make an extension method on SqlTransaction
passing it to Execute like so:
transaction.Connection.Execute(sql, p, transaction);
lacoder
Software developer Using Asp.net MVC3,MVC4 with C#, CSS3, JQUERY,AngularJs, HTML5.
Updated on July 08, 2022Comments
-
lacoder almost 2 years
I have a stored procedure in this format
CREATE PROCEDURE SP_MYTESTpROC @VAR1 VARCHAR(10), @VAR2 VARCHAR(20), @BASEID INT , @NEWID INT OUTPUT As Begin INSERT INTO TABLE_NAME(username, firstname) select @VAR1, @VAR2 WHERE ID = @BASEID SET @NEWID = SCOPE_IDENTITY() AS INT END
I am calling this stored procedure from C# code using dapper. My question is: how do I pass in the output parameter to the stored procedure while using dapper?
-
lacoder about 10 yearsHi Steve, I will try this out, it does seem reasonable and comprehensive. Yes I know about naming conventions for sprocs, what I meant to use was
spMyTestProc
-
lacoder about 10 yearsThis worked cleanly, however I had to change
First()
toFirstOrDefault()
asFirst()
kept returningsequence contains no elements
-
Steve about 10 yearsProbably you could remove it (FirstOrDefault). I have forgotten to clear it away (First) when copy/pasting from the example. (And in that example there is a reason because they have a return @a not present in your sp)
-
lacoder about 10 yearsYes! I have just taken the 'FirstOrDefault() out and it worked.
-
user1790300 about 9 yearsIf TestProc were performing inserts and you were calling .Execute instead of .Query, would there be a way to batch the proc calls and get the out parameter for each call that was made in batch and return values?
-
Steve about 9 yearsI am not sure of that. Probably yes, but I suggest you to post a new question on this. (Dapper tag) so you could get the attention of the master minds of Dapper that are very active users of this site.
-
Jason Goemaat over 2 yearsI think
AddDynamicParams(parameters)
should beparam
instead ofparameters
, but I can't edit just that as it has to be 6 characters.