Динамические предложения WHERE в SqlDataSource

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

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

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

SELECT * FROM MyTable

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

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

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

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

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

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


person Windy    schedule 09.02.2012    source источник


Ответы (4)


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

Имейте в виду, если вы это сделаете, не форматируйте строку. Используйте 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

person bryanmac    schedule 09.02.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>
person Snives    schedule 17.04.2012
comment
Могу ли я сделать что-то похожее на ваше для моей проблемы здесь: stackoverflow.com/questions/25309010/ - person SearchForKnowledge; 14.08.2014

Вы можете установить 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 не бесплатны ;) Если вас это беспокоит, то решение Bryanmac вполне приемлемо.

person paris    schedule 27.03.2012

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

person Rubens Farias    schedule 09.02.2012