2012-01-28 11 views
0

いくつかのプロジェクトでSQL Server用の再利用可能なデータアクセスレイヤーを作成しています。私は適切な方法を見つけることに問題があります.NETのdecimalをクエリのパラメータとして渡します。最も明白な方法:10進数と文字列をSqlParameterとして渡す適切な方法

cmd.Parameters.AddWithValue("@P0", parameterValue); 

はほとんどうまくいきます。値はDBに正しく格納されますが、SqlClientは実際の値から正確な型を推測します。したがって、アプリケーションが12345.678を渡すと、@ P0はNUMERIC(8,3)と宣言されます。まったく同じクエリが他の値と一緒に使用されると、その値の精度と位取りが宣言されます。私には分かっていないが、SQL Serverではこれらのクエリは等しくなく、それぞれがsys.dm_exec_cached_plansに別々のエントリを取得します。 stringとまったく同じ問題があります。長さごとに異なるクエリプランがあります。

いくつかのアプリケーションでは、1分あたりの記録が非常に大きく、それぞれが5〜10個の0〜の値を持っています(一部のセンサーデータ、通貨値)。ほとんどの各INSERTは独自のクエリプランを取得し、数日後には、同じクエリプランの100,000以上のバージョンがキャッシュされ、数GB以上のRAMを使用しています。

私の考えは、すべての可能なタイプをいくつかの任意のタイプにまとめることです。 decimalの場合、精度が20より低いときは20に設定します。精度が20より大きい場合は、実際の精度(たとえば24,28,32,36)よりも4で割り切れる最小値として設定します。スケール(最小2、次にステップ2)と文字列(最小128、次に2の累乗)についても同様です。この方法では問題を制御し続けるようです - 私は100kではなく各クエリで約100種類のバリアントプランを見てきましたが、SQL Serverはバッファプール用のメモリを使用しています。

この方法は間違っていますか? decimalsがロードされたSqlClientとクエリを使用しているときに、クエリプランキャッシュを管理下に保つためのより良い方法がありますか? - このDALの目的は、多くのDBMS(SQL Serverの、MS Accessの、Firebirdの、オラクル現時点では)ための抽象層を作成することですので、

  • 使用ストアドプロシージャを:私が行うことができないものの

    一覧。

  • 私の仲間のチームメイトに、各変数の実際のタイプをどうにかして渡すように強制する - それは残酷なものだからです。
  • ゴミ箱このDALは、昔ながらのDbProviderFactoryを使用して、それが1990年代のようなパラメータを作成 - このDALはまた、などのSQL方言、DB構造の作成、
  • ゴミ箱このDALのためのクエリの作成を処理し、NHibernateのような「正しい」DAOを使用しているため - それはここに発明されなかったからです。
  • この質問はdba.stackexchange.comにお願いします.SqlClientには問題があり、SQL Server自体ではなく、私が使用する方法に問題があるためです。

答えて

2

ここで重要な問題は、SQLドライバがパラメータのサイズ、スケール、および精度を決定できるようにしたことです。パラメータの精度/スケール/サイズを制限してクエリプランの数を減らす考えも正しいと言えます。文字列の場合、予想される最大値にサイズを設定できます。大きいサイズのパラメータ文字列と小さいサイズのvarcharを比較すると正しく動作します。小数点以下の小数点以下を丁寧に選ぶことも正しいと思います。 1組の精度/スケールだけに絞り込むことができるかどうかを確認してください。可能であれば(作業中のプロジェクトではうまく機能しました)可能性があります。それを行うと、SQLクエリごとに1つのクエリプランに行くことができます。

+0

良い点は、NUMERIC(38,8)に小数点のデフォルトタイプを設定すると考えられるすべてのケースを処理する必要があります。何らかの理由で誰かが小数点以下8桁以上の数値を渡した場合は、スケールを変更して精度を最大値に保ちます。今では、なぜ私は最初にvarchar(8000)と数値(38,8 + n)に行くのではなく、多くの値の複雑なアイデアを考え出したのだろうと言いました。 – MagnatLU

関連する問題