Динамические предложения WHERE в SqlDataSource - PullRequest
4 голосов
/ 09 февраля 2012

Я использую SqlDataSource в очень простом приложении.Я разрешаю пользователю устанавливать несколько параметров поиска для команды выбора SDS через TextBoxes, по одному TextBox на параметр (например, txtFirstName, txtLastName и т. Д.).Я планирую использовать обработчик события нажатия кнопки, чтобы установить свойство SelectCommand SqlDataSource, которое по умолчанию будет возвращать все записи (для моих целей здесь).Я хочу уточнить эту команду выбора, чтобы возможно добавить одно или несколько предложений WHERE в зависимости от того, вводит ли пользователь критерии поиска в каком-либо из моих текстовых полей.

Пример, если мне неясно:

По умолчанию свойство SelectCommand моего SqlDataSource будет выглядеть примерно так:

SELECT * FROM MyTable

Если пользователь вводит «Bob» в txtFirstName, я хочу, чтобы свойство SelectCommand выглядело так:

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

Если пользователь вводит «Jones» в txtLastName, я хочу, чтобы свойство SelectCommand выглядело так:

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

Мой вопрос:
Есть ли способ динамически создатьэти предложения WHERE без необходимости проверять пустые TextBox и создавать предложение WHERE вручную?

У моего маленького приложения есть только три параметра, так что грубое перемещение по этому пути не будет болезненным, но я удивляюсьесли бы был более простой способ сделать это плюс, возможно, мне нужно было бы добавить больше параметров в будущем.Кроме того, я могу добавить поиск по шаблону.

Ответы [ 4 ]

4 голосов
/ 17 апреля 2012

Если вы используете элемент управления 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>
2 голосов
/ 27 марта 2012

Вы можете установить 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])

В любом из них, если пользовательЕсли оставить текстовое поле пустым, оператор CASE или ISNULL заставит каждую часть оператора where сравниваться с самим собой, возвращая, таким образом, TRUE и создавая те же записи, как если бы эта часть предложения where вообще отсутствовала.,Это хорошее и простое решение, которое поддерживает статичность запроса и параметров и выдвигает логику на сторону SQL.

Однако, это приведет к (небольшому) снижению производительности по сравнению с простым произнесением "SELECT * FROM MyTable".Эти операции CASE и ISNULL не являются бесплатными;) Если это не проблема, решение Брайанмака вполне приемлемо.

2 голосов
/ 09 февраля 2012

Как вы сказали, не так уж сложно построить этот запрос, так как вы всегда И делаете поля в предложении where.

Имейте в виду, что если вы это сделаете, не форматируйте строку.Используйте SqlParameters, чтобы избежать SQL-инъекций: http://en.wikipedia.org/wiki/SQL_injection

Итак, вы можете начать с WHERE и для каждого текстового поля, имеющего значение, добавить [(fieldName)] = @ (имя поля) и связать этоПараметр sql.

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

Если вы хотите использовать Linq для SQL или структуру сущностей, см. этот построитель предикатов: http://www.albahari.com/nutshell/predicatebuilder.aspx

0 голосов
/ 09 февраля 2012

Вы можете использовать CancelSelectOnNullParameter=false, как показано в в этом примере

...