5

私が現在取り組んでいるシステムは、すべてのデータアクセスにストアドプロシージャを使用しています。現在Dapperを調べていますが(これまでのところ見栄えが良いです)、テンプレートを使用して作成されたDynamicParametersオブジェクトを使用できるかどうか疑問に思いましたが、パラメーターの1つを出力パラメーターにします。例えば:

SP:

CREATE PROCEDURE InsertPerson
  @ID int Output,
  @Name varchar(100),
  @DOB DateTime2
AS
--INSERT STATEMENT

SET @ID = SCOPE_IDENTITY()

POCO:

internal class Person
{
  public int ID { get; set; }
  public string Name { get; set; }
  public DateTime DOB { get; set; }
}

コード:

var procParams = new DynamicParameters(person);
connection.Execute("InsertPerson", procParams, commandType: CommandType.StoredProcedure);

// This is where i'm having the issue, can it be done?
person.ID = procParams.Get<int>("ID");

現在キーが見つからなかったため、エラーが発生しました。ストアドプロシージャパラメータをすべて手動で設定せずにID出力パラメータを取得する方法はありますか?

4

2 に答える 2

10

すばやく調整すると、テンプレートの値が置き換えられ、次のことが可能になりAddます

public void TestProcWithOutParameter()
{
    connection.Execute(
        @"CREATE PROCEDURE #TestProcWithOutParameter
@ID int output,
@Foo varchar(100),
@Bar int
AS
SET @ID = @Bar + LEN(@Foo)");
    var obj = new
    { // this could be a Person instance etc
        ID = 0,
        Foo = "abc",
        Bar = 4
    };
    var args = new DynamicParameters(obj);
    args.Add("ID", 0, direction: ParameterDirection.Output);
    connection.Execute("#TestProcWithOutParameter", args,
                 commandType: CommandType.StoredProcedure);
    args.Get<int>("ID").IsEqualTo(7);
}

それで十分ですか?ParameterDirection.ReturnValueまた、既存の値または新しい値のいずれかを使用することもできます。元のテンプレートに直接更新されないことに注意してください。値はインスタンスからフェッチする必要がありDynamicParametersます(図を参照)。

于 2011-11-04T20:25:29.227 に答える
2

コンストラクターを使用しDynamicParametersてテンプレートオブジェクトを指定する場合でも、それ@IDが出力パラメーターであることを指定する必要があります。最初に、テンプレートを介して、に設定されParameterDirection.Inputます。追加すると、更新された値を持つようにオーバーライドされ、次のようにパラメーター名で値を取得できます。

procParams.Add("@ID", dbType: DbType.Int32, direction: ParameterDirection.Output);
// ... execute ...
person.ID = procParams.Get<int>("@ID");

上で示したものに加えて、これを機能させることができ、クラスとコードを使用しました。

編集:コメントで説明されているように、ストアドプロシージャは、宣言されているよりも多くの引数を受け入れません。したがって、別のアプローチは、ストアドプロシージャを破棄し、インラインSQLを使用することです。クエリを使用すると、DapperはSQLステートメントで指定されていないパラメータを無視します。これは、この問題に取り組むための回避策です。

string sql = "INSERT INTO Person (Name, DOB) VALUES (@Name, @DOB) SELECT SCOPE_IDENTITY()";
decimal id = conn.Query<decimal>(sql, procParams).First();
person.ID = (int)id;

SCOPE_IDENTITY()intではなく10進数を返すことに注意してください。

もう1つのアイデアは、理想的ではないと思いますが、Dapperコードを変更Removeし、クラスにメソッドを追加しDynamicParametersて、不要なパラメーターを削除することです。ただし、ストアドプロシージャを満足させるために、すべてを削除するパラメータを指定するのに時間がかかるため、これではあまり節約できません。これを実装する場合は、parameters辞書から削除するキーを指定するときに大文字と小文字が区別されることに注意してください。

于 2011-11-04T15:04:06.667 に答える