SqlDataSource中的动态WHERE子句

时间:2012-02-09 00:15:21

标签: c# asp.net .net-2.0 sqldatasource dynamicquery

我在一个非常简单的应用程序中使用SqlDataSource。我允许用户通过TextBoxes为SDS的select命令设置几个搜索参数,每个参数一个TextBox(想想txtFirstName,txtLastName等)。我打算使用按钮单击事件处理程序来设置SqlDataSource的SelectCommand属性,默认情况下将返回所有记录(出于我的目的)。我想改进这个select命令,可能会添加一个或多个WHERE子句,具体取决于用户是否在我的任何TextBox中输入搜索条件。

我不清楚的例子:

默认情况下,我的SqlDataSource的SelectCommand属性将是这样的:

SELECT * FROM MyTable

如果用户在txtFirstName中输入“Bob”,我希望SelectCommand属性如下所示:

SELECT * FROM MyTable WHERE [FirstName]='Bob'

如果用户在txtLastName中输入“Jones”,我希望SelectCommand属性如下所示:

SELECT * FROM MyTable WHERE [FirstName]='Bob' AND [LastName]='Jones'

我的问题:
有没有办法动态创建这些WHERE子句,而不必测试空TextBox并手工构建WHERE子句?

我的小应用程序只有三个参数,所以粗暴强行通过这不会很痛苦,但我想知道是否有更简单的方法来做到这一点加上它可能我需要添加更多参数未来。另外,我可能想要添加通配符搜索。

4 个答案:

答案 0 :(得分:4)

如果您使用的是SqlDataSource控件,并且参数值来自页面控件,则可以提供ControlParameters并使用带有短路参数的静态where子句。这可能只是快速敲打一些代码的门票。

<asp:SqlDataSource ID="SqlDataSource1" runat="server" 
    ConnectionString="<%$ ConnectionStrings:AdventureworksConnectionString %>"
    SelectCommand=" SELECT FirstName, LastName, Age
                    FROM Contacts 
                    WHERE (FirstName=@FirstName or @FirstName = '')
                    AND (LastName = @LastName or @LastName = '' 
                    AND (Age = @Age or @Age = 0" >
        <SelectParameters>
            <asp:ControlParameter Name="FirstName" ControlID="TBFirstName" Type="String" />
            <asp:ControlParameter Name="LastName" ControlID="TBLastName" Type="String" />
            <asp:ControlParameter Name="Age" ControlID="TBAge" Type="Int16" />
        </SelectParameters>
    </asp:SqlDataSource>

答案 1 :(得分:2)

正如你所说,构建该查询并不困难,因为你总是在where子句中对字段进行AND运算。

请注意,如果您这样做,请不要格式化字符串。使用SqlParameters来避免SQL注入:http://en.wikipedia.org/wiki/SQL_injection

因此,您可以从WHERE开始,对于每个具有值的文本框,追加[(fieldName)] = @(fieldname)并绑定该sql参数。

请参阅:http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter.aspx

如果您愿意使用Linq to SQL或实体框架,请参阅此谓词构建器:http://www.albahari.com/nutshell/predicatebuilder.aspx

答案 2 :(得分:2)

您可以设置ConvertEmptyStringToNull="false"并执行:

SELECT * 
FROM MyTable 
WHERE [FirstName] = CASE @firstname WHEN '' THEN [FirstName] END AND 
    [LastName] = CASE @lastname WHEN '' THEN [LastName] END 

或者您可以设置ConvertEmptyStringToNull =“true”并执行:

SELECT * 
FROM MyTable 
WHERE [FirstName] = ISNULL(@firstname, [FirstName]) AND 
    [LastName] = ISNULL(@lastname,[LastName])

在其中任何一个中,如果用户将文本框留空,CASEISNULL语句会将where语句的每个部分与其自身进行比较,从而返回TRUE和产生相同的记录,就好像where子句的那部分根本不存在一样。这是一个很好的简单解决方案,它将查询和参数保持为静态,并将逻辑推送到SQL端。

然而,与仅仅"SELECT * FROM MyTable"相比,它会产生(小)性能影响。那些CASEISNULL操作不是免费的;)如果这是一个问题,Bryanmac的解决方案是完全可以接受的。

答案 3 :(得分:0)

您可以使用CancelSelectOnNullParameter=false

中显示的this example