Dynamic WHERE clauses in a SqlDataSource

坚强是说给别人听的谎言 提交于 2019-12-10 09:43:20

问题


I'm using a SqlDataSource in a very simple application. I'm allowing the user to set several search parameters for the SDS's select command via TextBoxes, one TextBox per parameter (think txtFirstName, txtLastName, etc). I'm planning on using a button click event handler to set the SqlDataSource's SelectCommand property which by default will return all records (for my purposes here). I want to refine this select command to possibly add one or more WHERE clauses depending on if the user enters search criteria in any of my TextBoxes.

Example in case I'm not being clear:

By default, my SqlDataSource's SelectCommand property will be something like this:

SELECT * FROM MyTable

If the user enters "Bob" in txtFirstName, I want to SelectCommand property to look like this:

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

If the user enters "Jones" in txtLastName, I want to SelectCommand property to look like this:

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

My question:
Is there a way to dynamically create these WHERE clauses without me having to test for empty TextBoxes and constructing a WHERE clause by hand?

My little application only has three parameters so brute forcing my way through this wouldn't be painful, but I've wondered if there was an easier way to do this plus it's possible I'll need to add more parameters in the future. Plus I may want to add wildcard searching.


回答1:


As you said, it's not too hard to construct that query since you're always ANDing the fields in the where clause.

Be aware if you do that, don't format the string. Use SqlParameters to avoid SQL Injection: http://en.wikipedia.org/wiki/SQL_injection

So, you can start with WHERE and for each text box that has a value, append [(fieldName)] = @(fieldname) and bind that sql parameter.

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

If you're willing to use Linq to SQL or the entity framework, see this predicate builder: http://www.albahari.com/nutshell/predicatebuilder.aspx




回答2:


If you are using a SqlDataSource control, and your parameter values are coming from page controls, you can supply ControlParameters and use a static where clause with short-circuited parameters. This might be just the ticket for quickly banging out some code.

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



回答3:


You could set ConvertEmptyStringToNull="false" and do:

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

Or you can set ConvertEmptyStringToNull="true" and do:

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

In either of those, if the user leaves the textbox blank, the CASE or ISNULL statement cause each part of the where statement to be compared to itself, thus returning TRUE and producing the same records as if that part of the where clause was not there at all. This is a good and simple solution that maintains the query and parameters static and pushes the logic to the SQL side.

However, it will have a (small) performance hit compared to just saying "SELECT * FROM MyTable". Those CASE and ISNULL operations aren't free ;) If that's a concern, Bryanmac's solution is a perfectly acceptable one.




回答4:


You can use CancelSelectOnNullParameter=false as shown in this example



来源:https://stackoverflow.com/questions/9203670/dynamic-where-clauses-in-a-sqldatasource

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!