web-dev-qa-db-ja.com

SqlCommandパラメーターを追加するときに「SqlDbType」と「size」を使用する必要があるのはいつですか?

これに関連する質問があります:

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

しかし、私は違いが何であり、異なる方法で問題があるかどうかを知りたいです。

私は通常、次のような構造を使用します。

using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(SQL, conn))
{
     cmd.CommandType = CommandType.Text;
     cmd.CommandTimeout = Settings.Default.reportTimeout;
     cmd.Parameters.Add("type", SqlDbType.VarChar, 4).Value = type;

     cmd.Connection.Open();

     using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
     {
         adapter.Fill(ds);
     }
      //use data                    
}

Cmdパラメーターを追加する方法はいくつかありますが、どれが最適か疑問に思います。

cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob";
cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob";
cmd.Parameters.Add("@Name").Value = "Bob";
cmd.Parameters.AddWithValue("@Name", "Bob");

Varcharを渡す際にフィールドの長さを保持することは、データベースで後で変更される可能性がある魔法の値なので、好ましくありません。これは正しいです?この方法(パフォーマンスまたはその他)でvarcharを渡す問題が発生する場合、デフォルトではvarchar(max)または同等のデータベースになっていると想定しています。これがうまくいくのはかなりうれしいです。

もっと気になる部分は、上記の3番目または4番目のオプションを使用している場合、SqlDbType列挙型が失われることです。まったくタイプを指定していません。これがうまくいかない場合はありますか?varcharがcharに間違ってキャストされる問題、またはその逆、またはおそらく10進数からお金の問題が想像できます...

データベースに関して言えば、私が言うフィールドタイプは長さよりも変化する可能性がはるかに低いので、保持する価値はありますか?

41
PeteT

私の経験では、私はこれらのことを確実にするでしょう:

  • パラメータのdata typeを定義するのはあなた自身であることを確認してください。 ADO.NETは推測において適切な仕事をしますが、場合によってはひどくオフになる可能性があります。そのため、この方法は避けます。

    cmd.Parameters.Add("@Name").Value = "Bob";
    cmd.Parameters.AddWithValue("@Name", "Bob");
    

    渡された値からパラメータのタイプをADO.NETに推測させるのは難しいのですが、何らかの理由でオフになっている場合は、追跡して見つけるのが非常に難しいバグです。 DBNull.Valueを渡すとどうなるか想像してみてください-ADO.NETはそのためにどのデータ型を選択する必要がありますか?

    ただ明示的に-あなたが望むタイプを言ってください!

  • 文字列パラメータを使用している場合は、明示的に長さを定義するを確認してください。したがって、このメソッドも回避します。

    cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob";
    

    長さを指定しない場合、ADO.NETはデフォルトで任意の値、値として渡された文字列の長さ、または他の何かにデフォルト設定される場合があります-よくわかりません。また、ストアドプロシージャが実際に期待する長さと一致しない場合、変換やその他の不快な驚きが発生する可能性があります。したがって、文字列を定義する場合は、その長さも定義してください!

あなたの場合、私にとって本当に有効な唯一のアプローチはここにあるものです:

cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob";

a)使用するデータ型を明示的に定義し、b)文字列の長さを明示的に定義するため。

56
marc_s

タイプを追加することにより、キャッシュされたクエリプランを使用して、リクエストのパフォーマンスが向上する可能性が高くなります。

MSDNからの引用は次のとおりです。

また、パラメータ化されたコマンドは、データベースサーバーが受信コマンドを適切なキャッシュクエリプランと正確に一致させるのに役立つため、クエリの実行パフォーマンスを向上させることができます。

読むべき詳細 実行計画のキャッシュと再利用

6
StefanE