1

さて、私はパラメータ化されたクエリの初心者です。なぜそれらを使用する必要があるのか​​ は理解していますが、正しい方法を示すリソース、または実際に機能する正しい方法を示すリソースが少なくとも1つ見つかりません.

私の質問は、私のコードが正しいかどうかです。コンパイルして正常に実行されますが、グリッドビューには何も返されません。

 protected void SearchButton_Click(object sender, EventArgs e)
{
    string searchBoxValue = SearchBox.Text;
    string columnNameValue = ColumnName.SelectedValue;
    columnNameValue.ToLower();

    SqlCommand searchCommand = new SqlCommand();
    searchCommand.Connection = connection;
    searchCommand.CommandText = "select firstname AS FirstName,lastname AS LastName, zipcode as ZipCode, phone AS Phone, email AS Email, cancersurvivor AS CancerSurvivor, ethnicity AS Ethnicity from registrants where @columnname = @searchterm";

    SqlParameter columnParam = new SqlParameter();
    columnParam.ParameterName = "@columnname";
    columnParam.Value = columnNameValue;

    SqlParameter searchBoxParam = new SqlParameter();
    searchBoxParam.ParameterName = "@searchterm";
    searchBoxParam.Value = searchBoxValue;

    searchCommand.Parameters.Add(columnParam);
    searchCommand.Parameters.Add(searchBoxParam);

    UpdateTable(searchCommand);

}

UpdateTable 関数は、SqlCommand オブジェクトを受け取り、DataAdapter オブジェクトを使用してコマンドを実行し、DataTable オブジェクトを埋めてから、gridview データソースをデータテーブル オブジェクトに設定し、それをバインドします。

前に言ったように、これを行う適切な方法を本当に探していますか? これを行うには、ストアド プロシージャが必要ですか? 私はこれらすべてと、なぜそれが機能しないのかについて混乱しています。

4

4 に答える 4

6

をパラメータ化することはできません@columnname。これはクエリのリテラルである必要があります。

あなたの声明

select 
 /* .... */
from registrants where @columnname = @searchterm

registrantsパラメータの値がたまたま同じである場合はすべての行を返すか、そうでない場合は行を返しません。

その名前の列があるかどうかを調べたり、@searchtermそこに存在するかどうかを確認したりしません。

これを安全な方法で行うにはcolumnNameValue、有効な列名のホワイトリストの 1 つと一致することを確認し (そのテーブルで可能な列名を知っている必要があるため)、それをクエリに連結する必要があります。検証されていないユーザー入力を連結しないでください。そうすれば、SQL インジェクションに身を任せることができます。

したがって、次のように実装できます

using System.Linq;

protected void SearchButton_Click(object sender, EventArgs e)
{
    string columnNameValue = ColumnName.SelectedValue.ToLower();

    var validColumnNames = new string[] { "firstname", "lastname", "zipcode" };

    if (!validColumnNames.Contains(columnNameValue))
    {
        throw new Exception("Unexpected column name " + columnNameValue);
    }

    /* ... code omitted */

    searchCommand.CommandText = "select firstname AS FirstName,lastname AS LastName, zipcode as ZipCode, phone AS Phone, email AS Email, cancersurvivor AS CancerSurvivor, ethnicity AS Ethnicity from registrants where " + columnNameValue + " = @searchterm";

    /* ... code omitted */
}
于 2012-12-19T20:43:30.823 に答える
2

パラメータ化されたコマンドの目的は、SQL インジェクションを防ぐことです。列の名前をパラメータ化することはできません。SQL はそれを文字列として受け取ります。

protected void SearchButton_Click(object sender, EventArgs e)
{
    string searchBoxValue = SearchBox.Text;
    string columnNameValue = ColumnName.SelectedValue;
    columnNameValue.ToLower();

    SqlCommand searchCommand = new SqlCommand();
    searchCommand.Connection = connection;
    //Put the column name directly in the request, but use a parameter for the search value
    searchCommand.CommandText = "select firstname AS FirstName,lastname AS LastName, zipcode as ZipCode, phone AS Phone, email AS Email, cancersurvivor AS CancerSurvivor, ethnicity AS Ethnicity from registrants where " + columnNameValue  + " = @searchterm";

    /* No need for this part
    SqlParameter columnParam = new SqlParameter();
    columnParam.ParameterName = "@columnname";
    columnParam.Value = columnNameValue;
    */

    SqlParameter searchBoxParam = new SqlParameter();
    searchBoxParam.ParameterName = "@searchterm";
    searchBoxParam.Value = searchBoxValue;

    //searchCommand.Parameters.Add(columnParam);
    searchCommand.Parameters.Add(searchBoxParam);

    UpdateTable(searchCommand);

}
于 2012-12-19T20:46:00.883 に答える
1

これを機能させるには、SQL ステートメントを動的に構築し、proc 内で sp_executesql を使用して実行する必要があります。

DECLARE @IntVariable int;
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);

/* Build the SQL string one time.*/
SET @SQLString =
     N'SELECT BusinessEntityID, NationalIDNumber, JobTitle, LoginID
       FROM AdventureWorks2012.HumanResources.Employee 
       WHERE BusinessEntityID = @BusinessEntityID';
SET @ParmDefinition = N'@BusinessEntityID tinyint';
/* Execute the string with the first parameter value. */
SET @IntVariable = 197;
EXECUTE sp_executesql @SQLString, @ParmDefinition,
                      @BusinessEntityID = @IntVariable;
/* Execute the same string with the second parameter value. */
SET @IntVariable = 109;
EXECUTE sp_executesql @SQLString, @ParmDefinition,
                      @BusinessEntityID = @IntVariable;

パラメータ化されたクエリを使用し、SQL インジェクションにさらされないという利点があります。

ソースはこちら。別の非常に便利なリンクはこれです。

于 2012-12-19T20:52:44.973 に答える
1

問題は、列名をパラメーターとして作成しようとしている方法にあります。フィルター処理する列を反映するように、クエリ全体を変更する必要があります。次のことを試してください。

protected void SearchButton_Click(object sender, EventArgs e)
{
    string searchBoxValue = SearchBox.Text;
    string columnNameValue = ColumnName.SelectedValue;
    columnNameValue.ToLower();

    SqlCommand searchCommand = new SqlCommand();
    searchCommand.Connection = connection;
    searchCommand.CommandText = String.Format("select firstname AS FirstName,lastname AS LastName, zipcode as ZipCode, phone AS Phone, email AS Email, cancersurvivor AS CancerSurvivor, ethnicity AS Ethnicity from registrants where {0} = @searchterm",columnNameValue);

    SqlParameter searchBoxParam = new SqlParameter();
    searchBoxParam.ParameterName = "@searchterm";
    searchBoxParam.Value = searchBoxValue;

    searchCommand.Parameters.Add(columnParam);
    searchCommand.Parameters.Add(searchBoxParam);

    UpdateTable(searchCommand);

}
于 2012-12-19T20:45:08.060 に答える