4

call_time、location、emergency_type という列を持つ call という名前のデータベース テーブルがあり、救急隊員、警察、消防士の 3 種類の緊急事態があります。Windows フォームで、CheckBoxes 'paramedics'、'police'、'firefighters' を作成しました。ユーザーの選択を満たすすべてのテーブル列を取得したいと考えています。

関数を作成しました:

public static DataTable GetHistory(DateTime from, DateTime to, bool paramedics, bool police, bool firefighters)
    {
        string select =
            "SELECT call_time, location, emergency_type where call_time between @from AND @to AND";
        if(paramedics)
        {
            select += " emergency_type = 'paramedics' ";
        }
        if(paramedics && police)
        {
           select +=" emergency_type = 'paramedics' OR emergency_type = 'police';
        }
        ...

    }

ただし、このコードは非常に汚いように見えます。30 種類の緊急事態があった場合、30 種類になるからです。if ステートメントをすべて書く前に年をとります。

選択できるオプションが多数ある場合、選択した検索条件に一致するデータを取得するための実践を共有していただければ幸いです。

ありがとう!

4

4 に答える 4

5

Emergency_type を文字列として使用する必要がある場合は、ブール値を渡す代わりに、緊急タイプのテキスト表現を含むリストを送信できます。たとえば、上記のコードを調整するには、メソッド シグネチャを次のように変更できます。

public static DataTable GetHistory(DateTime from, DateTime to, List<string> types)
{
 ..
}

次に、これらのようなリストを渡します(たとえば)

List<string> types = 
  new List<string> { "paramedics" };

or 

List<string> types = 
  new List<string> { "paramedics", "police" };

次に、where 句で SQL IN ステートメントを使用するようにクエリを調整できます。次に、文字列のリストをカンマ区切りの文字列に変換します

string values = "'paramedics', 'police'"

値変数を作成する簡単な方法は、使用することです

string values = string.Empty;
            types.ForEach(s =>
            {
               if (!string.IsNullOrEmpty(values))
                   values += ",";
               values += string.Format("'{0}'", s);

            });

ちなみに、パラメーター化されたコマンドを使用して、SQL インジェクションを回避できます。文字列を取得したら、簡単に実行できます

string select =
 "SELECT call_time, location, emergency_type where call_time between @from AND @to AND emergency_type IN " + values
于 2008-11-01T08:42:24.803 に答える
0

これは汚い方法です。

string select = "SELECT call_time, location, emergency_type where call_time between @from AND @to AND (1=0";

if(paramedics) { select += " OR emergency_type = 'paramedics' "; }
if(police)     { select += " OR emergency_type = 'police'"; }
if(xyz)        { select += " OR emergency_type = 'xyz'"; }

select += ")";
于 2008-11-01T08:35:51.337 に答える
0

文字列の連結は、厄介な脆弱性につながる可能性があるため、避ける必要があります。プログラムによるアクセスに関するベスト プラクティスを探している場合、ここでのベスト プラクティスは、パラメーター化されたクエリを使用することです。

安くしたい場合は、 in 句にパラメーターを取り、チェックされたチェックボックスのリストからその文字列を連結し、それを in 句のパラメーターの値として渡します。次のようになります。

where ... and emergency_type in (?)

もう 1 つの方法は、チェックされているチェックボックスの数をカウントし、in 句のパラメーターのリストを作成して、次のようにすることです。

where ... and emergency_type in(?,?...) -- as many params as there are checked checkboxes.

これらのどちらでも問題なく動作します。これらのタイプのクエリを使用して、独自の SQL コンストラクター メソッドを作成し、パラメーターの内部カウントとそのデータ型を保持し、SQL を動的に作成してから、適切なパラメーターの既知のリストを使用して準備を行いました。 .

Linq の学習を検討することもできます。

于 2008-11-01T17:04:35.353 に答える
0

ユーザーの比較値のリスト (@EmergencyList) を作成し、Contains 演算子を使用してパラメーター化されたクエリで SQL を使用します。

SELECT call_time, 
       location, 
       emergency_type 
where call_time between @from AND @to 
  AND CONTAINS( Emegency_Type, @EmergencyList )
于 2008-11-01T17:29:35.270 に答える