SQLCommandにパラメーターを渡すための最良の方法は何ですか?



Whats Best Method Pass Parameters Sqlcommand



解決:

そこで何が起こっているのですか?

のいくつかのオーバーロードのパラメータリストを引用します追加。これらは、コンストラクターのオーバーロードに直接対応する便利なメソッドです。SqlParameterクラス。基本的に、呼び出したコンビニエンスメソッドと同じシグネチャを持つコンストラクターを使用してパラメーターオブジェクトを構築し、次に呼び出します。このようなSqlParameterCollection.Add(SqlParameter):

SqlParameter foo = new SqlParameter(parameterName、dbType、size); this.Add(foo);

AddWithValueも同様ですが、さらに便利で、値を設定することもできます。ただし、実際にはフレームワークの欠陥を解決するために導入されました。 MSDNを引用するには、



の過負荷文字列を取り、オブジェクトとのあいまいさの可能性があるため、オブジェクトは非推奨になりました。SqlParameterCollection.Addオーバーロードは、文字列と文字列とともに整数を渡すと、パラメータ値または対応する値のいずれかであると解釈される可能性があるSqlDbType列挙値SqlDbType値。使用する名前と値を指定してパラメーターを追加する場合はいつでもAddWithValue。

コンストラクターのオーバーロードSqlParameterクラスは、インスタンスのプロパティを設定するための単なる便利なものです。これらはコードを短縮し、パフォーマンスにわずかな影響を与えます。コンストラクターはsetterメソッドをバイパスし、プライベートメンバーを直接操作する場合があります。違いがあれば、それほど多くはありません。



私は何をすべきか?

次の点に注意してください(MSDNから)

双方向パラメータと出力パラメータ、および戻り値の場合、次の値を設定する必要があります。サイズ。これは入力パラメーターには必要ありません。明示的に設定されていない場合、値は、パラメーター化されたステートメントの実行時に、指定されたパラメーターの実際のサイズから推測されます。

デフォルトのタイプはinputです。ただし、このようにサイズを推測できるようにし、パラメータオブジェクトをループでリサイクルする場合(パフォーマンスに関心があると言った場合)、サイズは最初の値によって設定され、それより長い値は次のようになります。クリップされました。明らかに、これは文字列などの可変長の値に対してのみ重要です。



ループ内で同じ論理パラメーターを繰り返し渡す場合は、ループの外側にSqlParameterオブジェクトを作成し、適切なサイズにすることをお勧めします。 varcharのサイズを大きくしすぎても無害なので、正確な最大値を取得するのがPITAの場合は、列の予想よりも大きく設定してください。反復ごとに新しいオブジェクトを作成するのではなく、オブジェクトをリサイクルしているため、ループの期間中のメモリ消費が発生する可能性があります 落とす オーバーサイジングに少し興奮しても。

正直なところ、何千もの呼び出しを処理しない限り、これは大きな違いにはなりません。AddWithValueは、サイズの問題を回避して、新しいオブジェクトを作成します。短くて甘くてわかりやすいです。数千をループする場合は、私のアプローチを使用してください。そうでない場合は、AddWithValueを使用すると、コードをシンプルで保守しやすくなります。


2008年はずっと前のことです

私がこれを書いてから数年で、世界は変わりました。新しい種類の日付があり、最近の日付の問題が拡大の影響について考えさせるまで、私の頭に浮かばなかった問題もあります。

用語に慣れていない人にとっては、拡大と縮小はデータ型変換の品質です。 intをdoubleに割り当てると、doubleは「幅が広い」ため、精度が低下することはありません。これは常に安全であるため、変換は自動的に行われます。これが、intをdoubleに割り当てることができる理由ですが、逆に明示的なキャストを行う必要があります。doubleからintへの変換は、精度が低下する可能性のある絞り込み変換です。

これは文字列に適用できます。NVARCHARはVARCHARよりも幅が広いため、VARCHARをNVARCHARに割り当てることができますが、逆の場合はキャストが必要です。 VARCHARが暗黙的にNVARCHARに広がるため、比較は機能します。 しかし、これはインデックスの使用を妨げるでしょう!

C#文字列はUnicodeであるため、AddWithValueはNVARCHARパラメーターを生成します。もう一方の端では、VARCHAR列の値が比較のためにNVARCHARに拡張されます。これはクエリの実行を停止しませんが、インデックスが使用されるのを防ぎます。これは悪いです。

あなたはそれについて何ができますか? 2つの可能な解決策があります。

  • パラメータを明示的に入力します。これは、AddWithValueがなくなることを意味します
  • すべての文字列列タイプをNVARCHARに変更します。

VARCHARを捨てることはおそらく最良の考えです。これは、予測可能な結果を​​伴う単純な変更であり、ローカリゼーションストーリーを改善します。ただし、これをオプションとして使用できない場合があります。

最近は、直接ADO.NETをあまり使用していません。 Linq2Sqlは今や私の選択の武器であり、このアップデートを書くという行為は、それがこの問題をどのように処理するのか疑問に思いました。 VARCHAR列を介したルックアップのためにデータアクセスコードをチェックしたいという突然の熱烈な欲求があります。


2019年と世界は前進しました また

Linq2SqlはdotnetCoreで使用できないため、Dapperを使用しています。 [N] VARCHARの問題はまだ問題ですが、今のところ埋もれていません。 ADOも使えると思いますので、その点で一巡しました。


使用することもできますAddWithValue()ですが、暗黙の型変換が間違っている可能性があることに注意してください。

cmd.Parameters.AddWithValue( '@ Name'、 'Bob'); 

私はあなたのオプション1を使用していました:

cmd.Parameters.Add( '@ Name'、SqlDbType.VarChar、20).Value = 'Bob';

これは問題なく動作しましたが、その後.AddWithValueを使い始めました。これは、非常に簡単です。何千回も使用しても問題は発生していません。念のために言っておきますが、私はほとんどの場合、クラスのプライベート変数を渡すので、暗黙的な型変換についてそれほど心配する必要はありません。