web-dev-qa-db-ja.com

C#コードでdapperを使用してストアドプロシージャに出力パラメーターを渡す

この形式のストアドプロシージャがあります

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を使用しながら、出力パラメーターをストアドプロシージャに渡すにはどうすればよいですか。

30
lacoder

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をストアドプロシージャのプレフィックスとして使用しないでください。システム定義のプロシージャ用に予約されています。それは悪い習慣であり、なぜリスクなのですか?

58
Steve

「ath's」の提案に加えて:リフレクションを回避するために、DynamicParmers.AddDynamicParams()は匿名オブジェクトを取得します。その後、次のような戻りパラメーターを追加できます。

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

匿名のparamオブジェクトの代わりに、dapper呼び出しでdynamicParametersオブジェクトを使用するようになりました。

(必要に応じて、出力パラメーターに対してこれを行うこともできます)

2
David Bridge

常に@id@id = @id OUTPUT)という名前のINTEGER型のOUTPUTパラメーターがある場合、sqlを渡す通常のDapper構文を使用できるこのような拡張メソッドを作成できます。文字列と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);
1
ath