2012-12-19 62 views
1

好吧我是参数化查询的noob。我明白为什么你应该使用它们,但是我找不到任何显示正确方法的资源,或者至少有一个显示实际工作的正确方法。ASP.NET C#参数化查询返回Nothing

所以我的问题是关于我的代码是否正确。它编译并运行得很好,但它在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对象和结合它。

就像我之前说过的,我真的想找到正确的方法来做到这一点?为了做到这一点,我需要一个存储过程吗?我很困惑这一切,为什么它不工作。

+0

在你的查询中你有'WHERE @parameter = @参数'是这个意思吗? –

回答

7

您不能参数化@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 */ 
} 
+0

我明白你的意思了。谢谢 – j0hnstew

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); 

} 
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); 

} 
+0

我实际上使用你的代码。伟大的工程,我明白为什么。谢谢 – j0hnstew

+0

@stewbydoo - 希望你实施了某种验证。我已经为我的回答添加了一个快速示例。 –

2

如果你想要这个工作,你必须动态地生成SQL statment与sp_executesql的执行proc中像这样:

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