SQLCommandにパラメーターを渡す最良の方法は何ですか?
-
08-07-2019 - |
質問
SQLCommandにパラメーターを渡す最適な方法は何ですか?できること:
cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob";
または
cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob";
または
cmd.Parameters.Add("@Name").Value = "Bob";
最初のものは、どういうわけか「より良い」もののようです。パフォーマンスまたはエラーチェックのいずれかです。しかし、もっと明確に知りたいです。
解決
AddWithValue()
を使用することもできますが、間違った暗黙的な型変換の可能性に注意してください。
cmd.Parameters.AddWithValue("@Name", "Bob");
他のヒント
そこで何が起きているのですか?
Add
のいくつかのオーバーロードのパラメーターリストを引用します。これらは、 SqlParameter
クラスのコンストラクタオーバーロードに直接対応する便利なメソッドです。基本的に、呼び出したコンビニエンスメソッドと同じシグネチャを持つコンストラクタを使用してパラメーターオブジェクトを構築し、次のように SqlParameterCollection.Add(SqlParameter)
を呼び出します。
SqlParameter foo = new SqlParameter(parameterName, dbType, size);
this.Add(foo);
AddWithValue
も同様ですが、値を設定することでさらに便利になります。ただし、実際にはフレームワークの欠陥を解決するために導入されました。 MSDNを引用するには、
Add
のオーバーロードは、 文字列とオブジェクトは廃止されました とのあいまいさが考えられるためSqlParameterCollection.Add
オーバーロードString
とSqlDbType
を取ります 列挙値 文字列を持つ整数は として解釈される パラメータ値または対応するSqlDbType
値。AddWithValue
を使用します パラメータを追加したいときはいつでも 名前と値を指定します。
SqlParameter
クラスのコンストラクタオーバーロードは、インスタンスプロパティを設定するための単なる便利さです。これらは、パフォーマンスにわずかな影響を与えてコードを短縮します。コンストラクターは、セッターメソッドをバイパスして、プライベートメンバーを直接操作できます。違いがあったとしても、それほど多くはありません。
どうすればよいですか
次のことに注意してください(MSDNから)
双方向および出力用 パラメータ、および戻り値、
Size
の値を設定する必要があります。これは 入力パラメーターには不要 明示的に設定されていない場合、値は の実際のサイズから推測 指定されたパラメータ パラメータ化されたステートメントが実行されます。
デフォルトのタイプは入力です。ただし、このようにサイズを推測できるようにし、パラメータオブジェクトをループでリサイクルすると(パフォーマンスに懸念があると言いました)、サイズは最初の値によって設定され、それ以降の値はより長くなりますクリップ。これは明らかに、文字列などの可変長の値でのみ重要です。
ループで同じ論理パラメーターを繰り返し渡す場合は、ループの外側でSqlParameterオブジェクトを作成し、適切にサイズ設定することをお勧めします。 varcharのサイズを大きくしすぎることは無害なので、正確な最大値を取得するのがPITAである場合は、列が予想するよりも大きく設定するだけです。反復ごとに新しいオブジェクトを作成するのではなくオブジェクトをリサイクルするため、オーバーサイズに少し興奮したとしても、ループ期間中のメモリ消費はおそらくドロップします。
真実を教えてください。何千もの呼び出しを処理しない限り、これはどれも大きな違いをもたらさないでしょう。 AddWithValue
は、サイズ変更の問題を回避して、新しいオブジェクトを作成します。短くて甘く、理解しやすいです。数千をループする場合は、私のアプローチを使用してください。そうでない場合は、 AddWithValue
を使用して、コードをシンプルで保守しやすくします。
2008年は昔です
これを書いてから数年で、世界は変わりました。新しい種類の日付があり、日付に関する最近の問題が拡大の意味について考えさせられるまで、私の心を横切らなかった問題もあります。
用語をよく知らない人にとっては、幅を広げたり狭めたりすることは、データ型変換の性質です。 intをdoubleに割り当てた場合、doubleは「幅が広い」ため、精度が失われることはありません。これは常に安全であるため、変換は自動的に行われます。これがintをdoubleに割り当てることができるが、明示的なキャストを行う必要がある他の方法に行く理由です-double to intは、精度を失う可能性のある狭い変換です。
T
確かに#1だと思います。ただし、Microsoftはエンタープライズライブラリのデータアクセスアプリケーションブロックでそれを実行しますが、SQLサーバーの場合は特にそうです。
以前はオプション1を使用していました
cmd.Parameters.Add(" @ Name&quot ;, SqlDbType.VarChar、20).Value =" Bob&quot ;;
これは正常に機能しましたが、その後、.AddWithValueを使用し始めました。何千回も使用しても問題は発生していません。念のため、クラスのプライベート変数はほとんど常に渡すので、暗黙的な型変換についてそれほど心配する必要はありません。
アプリケーションによって異なります。ストアドプロシージャパラメータの長さを変更してもDAOを変更する必要がないので、実際には2が好きです。それは私だけです。パフォーマンスのペナルティがあるかどうかはわかりません。