ASP.NET C#参数化查询返回任何内容

时间:2012-12-19 20:39:40

标签: asp.net sql parameterized

好的我是参数化查询的菜鸟。我理解为什么你应该使用它们,但我找不到任何显示正确方法的资源,或者至少有一个显示正确工作方式的资源。

所以我的问题是关于我的代码是否正确。它编译并运行得很好,但它在gridview中绝对没有返回。

 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数据源设置为datatable对象并绑定它。

就像我之前说的那样,我真的在寻找合适的方法吗?我需要一个存储过程才能执行此操作吗?我对这一切感到困惑,为什么它不起作用。

4 个答案:

答案 0 :(得分:6)

您无法参数化@columnname。这需要是您查询中的文字。

您的陈述

select 
 /* .... */
from registrants where @columnname = @searchterm
如果参数的值恰好相同或没有行,

将返回registrants的所有行。

它不会查看是否有该名称的列,并查看其中是否存在@searchterm

要以安全的方式执行此操作,您需要检查columnNameValue是否与有效列名称的白名单匹配(因为您必须知道该表中可能的列名称)并将其连接到您的查询中。 不要连接未经验证的用户输入。,因为那时你可以自己打开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 */
}

答案 1 :(得分:2)

paramtrized命令的目的是防止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);

}

答案 2 :(得分: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);

}

答案 3 :(得分: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注入。

来源here。 另一个非常有用的链接is this