sql-server 在C#代码中使用dapper将输出参数传递给存储过程

4xrmg8kj  于 2022-10-31  发布在  C#
关注(0)|答案(3)|浏览(244)

我有一个这种格式的存储过程

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

我使用Dapper从C#代码调用此存储过程。我的问题是:在使用dapper时,如何将输出参数传递给存储过程?

dy2hfwbg

dy2hfwbg1#

只需搜索Test.cs文件,您就可以找到此示例

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);
    }

因此,我假设您的C#代码可以编写为

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");
    }

顺便说一句,不要使用SP作为存储过程的前缀。它是为系统定义的过程保留的,如果Microsoft决定使用相同的名称,您可能会发现自己遇到麻烦。尽管这可能是一种不好的做法,但为什么要冒险呢?

lymnna71

lymnna712#

进一步对“阿特米斯”的建议:为了避免反射,DynamicParmers.AddDynamicParams()接受一个匿名对象,在该对象之后可以添加如下所示的返回参数...

var param = new { A="a", B="b" };
var dynamicParameters = new DynamicParameters();
dynamicParameters.AddDynamicParams(param);
dynamicParameters.Add("return", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

现在在dapper调用中使用dynamicParameters对象而不是匿名param对象。
(You如果愿意,也可以对输出参数执行此操作)

xxls0lw8

xxls0lw83#

如果您总是有一个名为@id@id = @id OUTPUT)的INTEGER类型的OUTPUT参数,则可以创建一个如下所示的扩展方法,该方法允许您使用常规Dapper语法传递sql字符串和anonymous对象:

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;
        }

这使用反射读取所有属性,但是如果您能够承受这个代价,就不必为每个调用都建立DynamicParameters的样板。
对于事务,在SqlTransaction上创建一个扩展方法,将其传递给Execute,如下所示:

transaction.Connection.Execute(sql, p, transaction);

相关问题