サーチ…


パラメーター

パラメータ詳細
this cnn 基礎となるデータベース接続 - thisは拡張メソッドを示します。接続が開いている必要はありません。開いていなければ自動的に開閉します。
<T> / Type (オプション)返すオブジェクトの型。非ジェネリック/非Type APIが使用されてdynamic場合は、クエリごとに返される列名ごとに名前が付けられたプロパティをシミュレートするdynamicオブジェクトが行ごとに返されます(このdynamicオブジェクトはIDicionary<string,object>も実装しIDicionary<string,object> )。
sql 実行するSQL
param (オプション)含めるパラメータ。
transaction (オプション)コマンドに関連付けるデータベーストランザクション
buffered (オプション)リストにデータを事前に消費するかどうか(デフォルト)、開いているIEnumerableをライブリーダーで公開するか
commandTimeout (オプション)コマンドで使用するタイムアウト。指定されていない場合、 SqlMapper.Settings.CommandTimeoutが指定されているとみなされます。
commandType 実行されるコマンドのタイプ。デフォルトはCommandText

備考

パラメータを表現するための構文は、RDBMSによって異なります。上記のすべての例では、SQL Server構文、つまり@foo使用しています。しかし、 ?foo:fooもうまく動作するはずです。

基本的なパラメータ化されたSQL

Dapperを使用すると、完全にパラメータ化されたSQLを使用してベストプラクティスを簡単に実行できます。

ボビーテーブル

パラメータは重要なので、大まかにそれを正しく取得することができます。あなたは自分のRDBMSのための通常の方法であなたのパラメータを表現する(通常は@foo?fooまたは:foo )と呼ばれるメンバー持つオブジェクトDapperの与えるfoo 。これを行う最も一般的な方法は、匿名型です:

int id = 123;
string name = "abc";
connection.Execute("insert [KeyLookup](Id, Name) values(@id, @name)",
    new { id, name });

以上です。 Dapperは必要なパラメータを追加し、すべてが機能するはずです。

オブジェクトモデルの使用

既存のオブジェクトモデルをパラメータとして使用することもできます。

KeyLookup lookup = ... // some existing instance
connection.Execute("insert [KeyLookup](Id, Name) values(@Id, @Name)", lookup);

Dapperはcommand-textを使ってオブジェクトのどのメンバーを追加するかを決定します。 DescriptionIsActiveCreationDateような不必要なものは通常追加しません。これは明らかに発行したコマンドには関係しません。例えば、あなたのコマンドに以下のものが含まれているとします。

// TODO - removed for now; include the @Description in the insert

上記は単なるコメントであることを理解しようとはしません。

ストアドプロシージャ

ストアドプロシージャのパラメータは全く同じになりますが、dapperは何を含むべきか/含まないべきかを判断できません。利用可能なものはすべてパラメータとして扱われます。そのため、通常は匿名型が優先されます。

connection.Execute("KeyLookupInsert", new { id, name },
    commandType: CommandType.StoredProcedure);

バリューインライン化

場合によっては、保守性や表現力の面でパラメータの利便性が、パラメータとして扱うための性能のコストよりも凌駕されることがあります。たとえば、ページサイズが構成設定によって固定されている場合などです。または、ステータス値がenum値と一致しています。検討してください:

var orders = connection.Query<Order>(@"
select top (@count) * -- these brackets are an oddity of SQL Server
from Orders
where CustomerId = @customerId
and Status = @open", new { customerId, count = PageSize, open = OrderStatus.Open });

実際の唯一パラメータはcustomerId 。他の2つは実際には変更されない疑似パラメータです。これらを定数として検出すると、RDBMSはしばしばより良い仕事をすることができます。 Dapperには、 @name {=name}代わりに - {=name}という特殊な構文があります。これは数値型にのみ適用されます。 (これにより、SQLインジェクションからの攻撃面が最小限に抑えられます)。例は次のとおりです。

var orders = connection.Query<Order>(@"
select top {=count} *
from Orders
where CustomerId = @customerId
and Status = {=open}", new { customerId, count = PageSize, open = OrderStatus.Open });

Dapperは、SQLを発行する前に値をリテラルに置き換えるので、RDBMSは実際に次のように見えます。

select top 10 *
from Orders
where CustomerId = @customerId
and Status = 3

これは、RDBMSシステムがより良い意思決定を行うだけでなく、実際のパラメータが回避するクエリプランを開くときに特に便利です。たとえば、列述語がパラメータに対抗する場合、その列に特定の値を持つフィルタされた索引は使用できません。これは、 次の照会に、指定された値の1つから離れたパラメーターがある可能性があるためです。

リテラル値では、クエリオプティマイザは、将来のクエリで値が変更できないことがわかっているので、フィルタされたインデックスを使用できます。

リスト展開

データベースクエリの一般的なシナリオはIN (...)です。ここでのリストは実行時に生成されます。ほとんどのRDBMSにはこのための優れたメタファーがありません。これには汎用のクロスRDBMSソリューションはありません。代わりに、dapperは穏やかな自動コマンド拡張を提供します。必要なのは、 IEnumerable提供されるパラメータ値です。 @fooを含むコマンドは、 (@foo0,@foo1,@foo2,@foo3) (4つのアイテムのシーケンスに対して)展開されています。これの最も一般的な使用法はINです。

int[] orderIds = ...
var orders = connection.Query<Order>(@"
select *
from Orders
where Id in @orderIds", new { orderIds });

これは自動的に展開され、複数行フェッチの適切なSQLが発行されます。

select *
from Orders
where Id in (@orderIds0, @orderIds1, @orderIds2, @orderIds3)

@orderIds0などのパラメータが@orderIds0から取得された値として追加されます。この機能が誤って使用されていないことを確認するために、有効なSQLではないという事実は意図的なものです。この機能は、SQL ServerのOPTIMIZE FOR / UNKNOWNクエリヒントでも正しく動作します。あなたが使用する場合:

option (optimize for
    (@orderIds unknown))

これを正しく展開します:

option (optimize for
    (@orderIds0 unknown, @orderIds1 unknown, @orderIds2 unknown, @orderIds3 unknown))

複数の入力セットに対する操作の実行

時々、あなたは同じことを何度もやりたいと思っています。 最も外側のパラメータ(通常は単一の匿名型またはドメインモデルインスタンス)が実際にIEnumerableシーケンスとして提供されている場合、DapperはこれをExecuteメソッドでサポートします。例えば:

Order[] orders = ...
// update the totals
connection.Execute("update Orders set Total=@Total where Id=@Id", orders);

ここで、dapperは単純に私たちのデータを単純にループしています。

Order[] orders = ...
// update the totals
foreach(Order order in orders) {
    connection.Execute("update Orders set Total=@Total where Id=@Id", order);
}

この使用法は、すべての「複数のアクティブな結果セット」に明示的に設定された接続でasync APIと組み合わせると特に興味深いものになります。この使用法では、dapperは自動的に操作をパイプラインするので、行ごとの遅延コストを払っていません。これにはやや複雑な使い方が必要ですが、

await connection.ExecuteAsync(
    new CommandDefinition(
        "update Orders set Total=@Total where Id=@Id", 
         orders, flags: CommandFlags.Pipelined))

ただし、テーブル値のパラメータを調べることもできます。

擬似位置パラメータ(名前付きパラメータをサポートしないプロバイダ用)

一部のADO.NETプロバイダ(特にOleDB)は、 名前付きパラメータをサポートしていません。パラメータは位置によってのみ指定され、 ?プレースホルダ。 Dapperはどのメンバをこれらのために使うのか分からないので、dapperは別の構文を許します?foo? ;これは、他のSQL変種の@fooまたは:fooと同じですが、dapperはパラメータトークンを完全に置き換えます?クエリを実行する前に

これはリスト展開などの他の機能と組み合わせて機能するので、以下が有効です:

string region = "North";
int[] users = ...
var docs = conn.Query<Document>(@"
     select * from Documents
     where Region = ?region?
     and OwnerId in ?users?", new { region, users }).AsList();

したがって、 .regionおよび.usersメンバーは使用され、発行されるSQLは(たとえば、3人のユーザーが)です。

     select * from Documents
     where Region = ?
     and OwnerId in (?,?,?)

ただし、この機能を使用する場合、dapper 同じパラメータを複数回使用することできません 。これは、同じパラメータ値(大きな値でもよい)を複数回追加する必要がないようにするためです。同じ値を複数回参照する必要がある場合は、次のように変数を宣言することを検討してください。

declare @id int = ?id?; // now we can use @id multiple times in the SQL

変数が使用できない場合は、パラメーターに重複メンバー名を使用できます。これにより、値が複数回送信されていることが明らかになります。

int id = 42;
connection.Execute("... where ParentId = $id0$ ... SomethingElse = $id1$ ...",
      new { id0 = id, id1 = id });


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow