Использование параметризованных запросов с помощью элемента управления SqlDataSource (C#)

Скотт Митчелл

Загрузить PDF-файл

В этом руководстве мы продолжим изучение элемента управления SqlDataSource и узнаем, как определить параметризованные запросы. Параметры можно указать как декларативно, так и программным способом. Их можно извлечь из нескольких расположений, таких как строка запроса, состояние сеанса, другие элементы управления и многое другое.

Введение

В предыдущем руководстве мы узнали, как использовать элемент управления SqlDataSource для получения данных непосредственно из базы данных. С помощью мастера настройки источника данных можно выбрать базу данных, а затем выбрать столбцы, возвращаемые из таблицы или представления; введите пользовательскую инструкцию SQL; или используйте хранимую процедуру. Независимо от того, выбираете ли столбцы из таблицы или представления или вводите пользовательскую инструкцию SQL, свойству элемента управления SelectCommand SqlDataSource назначается результирующая нерегламентированная инструкция SQL SELECT , и именно эта SELECT инструкция выполняется при вызове метода SqlDataSource Select() (программно или автоматически из веб-элемента управления данных).

В инструкциях SQL SELECT , используемых в демонстрациях предыдущего руководства, отсутствуют WHERE предложения. SELECT В инструкции WHERE предложение можно использовать для ограничения возвращаемых результатов. Например, чтобы отобразить имена продуктов стоимостью более 50,00 долл. США, можно использовать следующий запрос:

SELECT ProductName
FROM Products
WHERE UnitPrice > 50.00

Как правило, значения, используемые в WHERE предложении, определяются каким-либо внешним источником, например значением строки запроса, переменной сеанса или введенными пользователем данными из веб-элемента управления на странице. В идеале такие входные данные задаются с помощью параметров. В Microsoft SQL Server параметры обозначаются с помощью @parameterName, как в:

SELECT ProductName
FROM Products
WHERE UnitPrice > @Price

SqlDataSource поддерживает параметризованные запросы как для инструкций, так и INSERTдля SELECT инструкций , UPDATEи DELETE . Кроме того, значения параметров могут быть автоматически извлечены из различных источников, например строка запроса, состояние сеанса, элементы управления на странице и т. д. или могут быть назначены программным способом. В этом руководстве мы посмотрим, как определить параметризованные запросы, а также как указать значения параметров как декларативно, так и программно.

Примечание

В предыдущем руководстве мы сравнили ObjectDataSource, который был нашим инструментом выбора по сравнению с первыми 46 учебниками, с SqlDataSource, отметив их концептуальное сходство. Эти сходства также распространяются на параметры. Параметры ObjectDataSource, сопоставленные с входными параметрами для методов на уровне бизнес-логики. При использовании SqlDataSource параметры определяются непосредственно в SQL-запросе. Оба элемента управления имеют коллекции параметров для своих Select()методов , Insert(), Update()и Delete() , и оба могут иметь значения параметров, заполненные из предварительно определенных источников (значения строки запросов, переменные сеанса и т. д.) или назначаться программным способом.

Создание параметризованного запроса

Мастер настройки источника данных элемента управления SqlDataSource предлагает три способа определения команды, выполняемой для получения записей базы данных:

  • Выбрав столбцы из существующей таблицы или представления,
  • Путем ввода пользовательской инструкции SQL или
  • Выбор хранимой процедуры

При выборе столбцов из существующей таблицы или представления параметры для WHERE предложения необходимо указать в диалоговом окне Добавление WHERE предложения. Однако при создании настраиваемой инструкции SQL можно ввести параметры непосредственно в WHERE предложение (с помощью @parameterName для обозначения каждого параметра). Хранимая процедура состоит из одной или нескольких инструкций SQL, и эти инструкции можно параметризовать. Однако параметры, используемые в инструкциях SQL, должны передаваться в качестве входных параметров хранимой процедуре.

Так как создание параметризованного запроса зависит от того, как заданы sqlDataSource SelectCommand , рассмотрим все три подхода. Чтобы начать работу, откройте страницу ParameterizedQueries.aspx в папкеSqlDataSource, перетащите элемент управления SqlDataSource из панели элементов на Designer и задайте для этого ID элемента значение Products25BucksAndUnderDataSource. Затем щелкните ссылку Настройка источника данных в смарт-теге элемента управления. Выберите базу данных для использования (NORTHWINDConnectionString) и нажмите кнопку Далее.

Шаг 1. Добавление предложения WHERE при выборе столбцов из таблицы или представления

При выборе данных, возвращаемых из базы данных с помощью элемента управления SqlDataSource, мастер настройки источника данных позволяет просто выбрать столбцы для возврата из существующей таблицы или представления (см. рис. 1). При этом автоматически создается инструкция SQL SELECT , которая отправляется в базу данных при вызове метода SqlDataSource Select() . Как и в предыдущем руководстве, выберите таблицу Products из раскрывающегося списка и проверка ProductIDстолбцы , ProductNameи UnitPrice .

Выбор столбцов для возврата из таблицы или представления

Рис. 1. Выбор столбцов, возвращаемых из таблицы или представления (щелкните для просмотра полноразмерного изображения)

Чтобы включить WHERE предложение в инструкцию SELECT , нажмите кнопку WHERE , которая открывает диалоговое окно Добавление WHERE предложения (см. рис. 2). Чтобы добавить параметр для ограничения результатов, возвращаемых запросом SELECT , сначала выберите столбец для фильтрации данных. Затем выберите оператор, используемый для фильтрации (=, <, <=, >и т. д.). Наконец, выберите источник значения параметра, например из строки запроса или состояния сеанса. После настройки параметра нажмите кнопку Добавить, чтобы включить его в SELECT запрос.

В этом примере давайте возвращаем только те результаты, где UnitPrice значение меньше или равно 25,00 долл. США. Поэтому выберите UnitPrice в раскрывающемся списке Столбец и <= в раскрывающемся списке Оператор. При использовании жестко закодированного значения параметра (например, 25,00 долл. США) или программном указании значения параметра выберите Нет в раскрывающемся списке Источник. Затем введите жестко закодированное значение параметра в текстовое поле Значение 25.00 и завершите процесс, нажав кнопку Добавить.

Ограничение результатов, возвращаемых из диалогового окна Добавление предложения WHERE

Рис. 2. Ограничение результатов, возвращаемых из диалогового окна Добавление WHERE предложения (щелкните для просмотра полноразмерного изображения)

После добавления параметра нажмите кнопку ОК, чтобы вернуться к мастеру настройки источника данных. Оператор SELECT в нижней части мастера теперь должен содержать WHERE предложение с параметром с именем @UnitPrice:

SELECT [ProductID], [ProductName], [UnitPrice]
FROM [Products]
WHERE ([UnitPrice] <= @UnitPrice)

Примечание

Если в предложении указано несколько условий WHERE из диалогового окна Добавление WHERE предложения, мастер объединяет их с оператором AND . Если необходимо включить OR в WHERE предложение (например, WHERE UnitPrice <= @UnitPrice OR Discontinued = 1), необходимо создать инструкцию SELECT на пользовательском экране инструкции SQL.

Завершите настройку SqlDataSource (нажмите кнопку Далее, затем Готово), а затем проверьте декларативную разметку SqlDataSource. Теперь разметка включает коллекцию <SelectParameters> , в которой указаны источники параметров в SelectCommand.

<asp:SqlDataSource ID="Products25BucksAndUnderDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand=
        "SELECT [ProductID], [ProductName], [UnitPrice]
        FROM [Products] WHERE ([UnitPrice] <= @UnitPrice)">
    <SelectParameters>
        <asp:Parameter DefaultValue="25.00" Name="UnitPrice" Type="Decimal" />
    </SelectParameters>
</asp:SqlDataSource>

При вызове UnitPrice метода SqlDataSource Select() значение параметра (25.00) применяется к параметру @UnitPriceSelectCommand в перед отправкой в базу данных. В результате из Products таблицы возвращаются только те продукты, которые меньше или равны 25,00 долл. США. Чтобы подтвердить это, добавьте Элемент GridView на страницу, привяжите его к этому источнику данных, а затем просмотрите страницу в браузере. Вы должны увидеть только те продукты, которые меньше или равны 25,00 долл. США, как показано на рисунке 3.

Отображаются только те продукты, которые меньше или равны 25,00 долл. США

Рис. 3. Отображаются только те продукты, которые меньше или равно 25,00 долл. США (щелкните для просмотра полноразмерного изображения)

Шаг 2. Добавление параметров в настраиваемую инструкцию SQL

При добавлении настраиваемой инструкции SQL можно явно ввести WHERE предложение или указать значение в ячейке Фильтр построителя запросов. Чтобы продемонстрировать это, давайте отобразим только те продукты в GridView, цены которых меньше определенного порогового значения. Начните с добавления элемента TextBox на страницу ParameterizedQueries.aspx , чтобы получить это пороговое значение от пользователя. Присвойте свойству TextBox значение IDMaxPrice. Добавьте веб-элемент управления Button и задайте для его Text свойства значение Display Matching Products .

Затем перетащите Элемент GridView на страницу и из его смарт-тега выберите для создания sqlDataSource с именем ProductsFilteredByPriceDataSource. В мастере настройки источника данных перейдите к экрану Укажите пользовательскую инструкцию SQL или хранимую процедуру (см. рис. 4) и введите следующий запрос:

SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice

После ввода запроса (вручную или с помощью построителя запросов) нажмите кнопку Далее.

Возвращает только те продукты, которые меньше или равно значению параметра

Рис. 4. Возврат только тех продуктов, которые меньше или равно значению параметра (щелкните для просмотра полноразмерного изображения)

Так как запрос содержит параметры, на следующем экране мастера появится запрос на ввод источника значений параметров. Выберите Элемент Управления в раскрывающемся списке Источник параметров и MaxPrice (значение элемента управления ID TextBox) в раскрывающемся списке ControlID. Вы также можете ввести необязательное значение по умолчанию, которое будет использоваться в случае, если пользователь не ввел текст в MaxPrice элемент TextBox. Пока не вводите значение по умолчанию.

Текстовое свойство MaxPrice TextBox используется в качестве источника параметров

Рис. 5. Свойство MaxPrice TextBox Text используется в качестве источника параметров (щелкните для просмотра полноразмерного изображения)

Завершите работу мастера настройки источника данных, нажав кнопку Далее, а затем — Готово. Декларативная разметка для GridView, TextBox, Button и SqlDataSource:

Maximum price:
$<asp:TextBox ID="MaxPrice" runat="server" Columns="5" />
 
<asp:Button ID="DisplayProductsLessThanButton" runat="server"
    Text="Display Matching Products" />
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False"
    DataSourceID="ProductsFilteredByPriceDataSource" EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            HtmlEncode="False" DataFormatString="{0:c}"
            SortExpression="UnitPrice" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="ProductsFilteredByPriceDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand=
        "SELECT ProductName, UnitPrice 
        FROM Products WHERE UnitPrice <= @MaximumPrice">
    <SelectParameters>
        <asp:ControlParameter ControlID="MaxPrice" Name="MaximumPrice"
            PropertyName="Text" />
    </SelectParameters>
</asp:SqlDataSource>

Обратите внимание, что параметром в разделе SqlDataSource <SelectParameters> является ControlParameter, который включает дополнительные свойства, такие как ControlID и PropertyName. При вызове ControlParameter метода SqlDataSource Select() объект получает значение из указанного свойства веб-элемента управления и назначает его соответствующему параметру SelectCommandв . В этом примере MaxPrice в качестве @MaxPrice значения параметра используется свойство Text .

Просмотрите эту страницу в браузере. При первом посещении страницы или при отсутствии MaxPrice значения элемента TextBox в GridView записи не отображаются.

При пустом поле MaxPrice TextBox не отображается записей

Рис. 6. При пустом MaxPrice поле TextBox не отображается записей (щелкните для просмотра полноразмерного изображения)

Причина, по которой продукты не отображаются, заключается в том, что по умолчанию пустая строка для значения параметра преобразуется в значение базы данных NULL . Так как сравнение [UnitPrice] <= NULL всегда принимает значение False, результаты не возвращаются.

Введите в текстовое поле значение, например 5.00, и нажмите кнопку Показать соответствующие продукты. При обратной отправке SqlDataSource сообщает GridView о том, что один из его источников параметров изменился. Следовательно, GridView повторно привязывается к SqlDataSource, отображая эти продукты меньше или равны 5,00 долл. США.

Отображаются продукты, не превышающие 5,00 долл. США

Рис. 7. Отображаются продукты, не превышающие 5,00 долл. США (щелкните для просмотра полноразмерного изображения)

Первоначальное отображение всех продуктов

Вместо отображения продуктов при первой загрузке страницы может потребоваться отобразить все продукты. Один из способов вывести список всех продуктов всякий раз MaxPrice , когда TextBox пуст, заключается в том, чтобы задать значение параметра по умолчанию на безумно высокое значение, например 10000000, так как маловероятно, что Northwind Traders когда-либо будет иметь запасы, цена за единицу которых превышает $1,000,000. Однако этот подход является недальновидным и может не работать в других ситуациях.

В предыдущих руководствах по декларативным параметрам и фильтрации основных и подробных данных с помощью раскрывающегося списка мы сталкивались с аналогичной проблемой. Наше решение — поместить эту логику на уровень бизнес-логики. В частности, BLL изучил входящее значение и, если оно было NULL или какое-либо зарезервированное значение, вызов был перенаправлен в метод DAL, который возвращал все записи. Если входящее значение было обычным фильтрующим значением, был выполнен вызов метода DAL, выполняющего инструкцию SQL, которая использовала параметризованное WHERE предложение с предоставленным значением.

К сожалению, мы обходим архитектуру при использовании SqlDataSource. Вместо этого необходимо настроить инструкцию SQL для интеллектуального захвата всех записей, @MaximumPrice если параметр имеет NULL или какое-либо зарезервированное значение. В этом упражнении давайте создадим его так, чтобы если @MaximumPrice параметр равен -1.0, то должны быть возвращены все записи (-1.0 работает как зарезервированное значение, так как ни в каких продуктах не может быть отрицательное UnitPrice значение). Для этого можно использовать следующую инструкцию SQL:

SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice OR @MaximumPrice = -1.0

Это WHERE предложение возвращает все записи, @MaximumPrice если параметр равен -1.0. Если значение параметра не -1.0равно , возвращаются только те продукты, значение которых UnitPrice меньше или равно значению @MaximumPrice параметра. Если задать для параметра значение @MaximumPrice по умолчанию , при первой загрузке страницы (или при пустом MaxPrice элементе TextBox), @MaximumPrice будет иметь значение -1.0 и будут отображаться все -1.0продукты.

Теперь отображаются все продукты при пустом поле MaxPrice TextBox

Рис. 8. Теперь отображаются все продукты при пустом MaxPrice поле TextBox (щелкните для просмотра полноразмерного изображения)

Существует несколько предостережений, которые следует отметить при этом подходе. Во-первых, следует понимать, что тип данных параметра определяется его использованием в SQL-запросе. Если изменить WHERE предложение с @MaximumPrice = -1.0 на @MaximumPrice = -1, среда выполнения обрабатывает параметр как целое число. При попытке присвоить элементу MaxPrice TextBox десятичное значение (например, 5,00), возникнет ошибка, так как не удается преобразовать значение 5,00 в целое число. Чтобы устранить эту проблему, убедитесь, что вы используете @MaximumPrice = -1.0 в предложении WHERE , или, что еще лучше, задайте ControlParameter для свойства объекта Type значение Decimal .

Во-вторых, добавив OR @MaximumPrice = -1.0 в WHERE предложение , обработчик запросов не может использовать индекс в UnitPrice (при условии, что он существует), что приводит к сканированию таблицы. Это может повлиять на производительность, если в таблице достаточно большое Products количество записей. Лучший подход — переместить эту логику в хранимую процедуру, в IF которой оператор будет выполнять SELECT запрос из Products таблицы без предложения, WHERE когда необходимо вернуть все записи, или в том случае, если WHERE предложение содержит только UnitPrice критерии, чтобы можно было использовать индекс.

Шаг 3. Создание и использование параметризованных хранимых процедур

Хранимые процедуры могут включать набор входных параметров, которые затем можно использовать в инструкциях SQL, определенных в хранимой процедуре. При настройке SqlDataSource для использования хранимой процедуры, принимающей входные параметры, эти значения параметров можно указать с помощью таких же методов, как и при использовании нерегламентированных инструкций SQL.

Чтобы проиллюстрировать использование хранимых процедур в SqlDataSource, создадим новую хранимую процедуру в базе данных Northwind с именем GetProductsByCategory, которая принимает параметр с именем @CategoryID и возвращает все столбцы продуктов, столбец которых CategoryID соответствует @CategoryID. Чтобы создать хранимую процедуру, перейдите на сервер Обозреватель и выполните детализацию NORTHWND.MDF базы данных. (Если Обозреватель сервера не отображается, откройте его, перейдя в меню Вид и выбрав параметр Сервер Обозреватель.)

В базе данных щелкните правой NORTHWND.MDF кнопкой мыши папку Хранимые процедуры, выберите Добавить новую хранимую процедуру и введите следующий синтаксис:

CREATE PROCEDURE dbo.GetProductsByCategory
(
      @CategoryID int
)
AS
SELECT *
FROM Products
WHERE CategoryID = @CategoryID

Щелкните значок Сохранить (или CTRL+S), чтобы сохранить хранимую процедуру. Вы можете проверить хранимую процедуру, щелкнув ее правой кнопкой мыши в папке Хранимые процедуры и выбрав Пункт Выполнить. Будет предложено ввести параметры хранимой процедуры (@CategoryIDв данном случае), после чего результаты будут отображаться в окне Вывод.

Хранимая процедура GetProductsByCategory при выполнении с <span class=@CategoryID 1" />

Рис. 9. Хранимая GetProductsByCategory процедура при выполнении с @CategoryID 1 (щелкните для просмотра полноразмерного изображения)

Давайте используем эту хранимую процедуру для отображения всех продуктов в категории «Напитки» в GridView. Добавьте новый элемент GridView на страницу и привяжите его к новому объекту SqlDataSource с именем BeverageProductsDataSource. Перейдите на экран Укажите настраиваемую инструкцию SQL или хранимую процедуру, выберите переключатель Хранимая процедура и выберите хранимую GetProductsByCategory процедуру из раскрывающегося списка.

Выберите хранимую процедуру GetProductsByCategory из списка Drop-Down.

Рис. 10. Выберите хранимую GetProductsByCategory процедуру из списка Drop-Down (щелкните для просмотра полноразмерного изображения)

Так как хранимая процедура принимает входной параметр (@CategoryID), при нажатии кнопки Далее будет предложено указать источник для значения этого параметра. Для параметра Beverages CategoryID задано значение 1, поэтому оставьте раскрывающийся список Источник параметров в поле Нет и введите 1 в текстовое поле DefaultValue.

Используйте значение Hard-Coded 1 для возврата продуктов в категории

Рис. 11. Используйте значение Hard-Coded 1, чтобы вернуть продукты в категории "Напитки" (щелкните для просмотра полноразмерного изображения)

Как показано в следующей декларативной разметке, при использовании хранимой процедуры свойству SqlDataSource SelectCommand присваивается имя хранимой процедуры, а свойствуSelectCommandTypeStoredProcedureприсваивается значение , указывающее, что SelectCommand является именем хранимой процедуры, а не нерегламентированной инструкцией SQL.

<asp:SqlDataSource ID="BeverageProductsDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="GetProductsByCategory" SelectCommandType="StoredProcedure">
    <SelectParameters>
        <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

Протестируйте страницу в браузере. Отображаются только те продукты, которые относятся к категории «Напитки», хотя отображаются все поля продукта, так как хранимая GetProductsByCategory процедура возвращает все столбцы из Products таблицы. Конечно, можно ограничить или настроить поля, отображаемые в GridView в диалоговом окне Изменение столбцов GridView.

Отображаются все напитки

Рис. 12. Отображаются все напитки (щелкните, чтобы просмотреть изображение в полном размере)

Шаг 4. Программный вызов инструкции Select() SqlDataSource

В примерах, которые мы видели в предыдущем и этом руководстве, элементы управления SqlDataSource привязаны непосредственно к GridView. Однако к данным элемента управления SqlDataSource можно получить программный доступ и перечислить в коде. Это может быть особенно полезно, если требуется запросить данные для их проверки, но не нужно отображать их. Вместо того, чтобы писать весь стандартный код ADO.NET для подключения к базе данных, указать команду и получить результаты, можно позволить SqlDataSource обрабатывать этот монотонный код.

Чтобы проиллюстрировать работу с данными SqlDataSource программным способом, представьте, что ваш босс обратился к вам с запросом на создание веб-страницы, отображающей имя случайно выбранной категории и связанные с ней продукты. То есть, когда пользователь посещает эту страницу, мы хотим случайным образом выбрать категорию из Categories таблицы, отобразить имя категории, а затем вывести список продуктов, относящихся к этой категории.

Для этого нам потребуется два элемента управления SqlDataSource, один для захвата случайной категории из Categories таблицы, а другой для получения продуктов категории. Мы создадим sqlDataSource, который извлекает запись случайной категории на этом шаге; На шаге 5 рассматривается создание SqlDataSource, который извлекает продукты категории.

Начните с добавления SqlDataSource в ParameterizedQueries.aspx и задайте для него ID значение RandomCategoryDataSource. Настройте его таким образом, чтобы он использовал следующий SQL-запрос:

SELECT TOP 1 CategoryID, CategoryName
FROM Categories
ORDER BY NEWID()

ORDER BY NEWID() возвращает записи, отсортированные в случайном порядке (см . раздел Использование NEWID() для случайной сортировки записей). SELECT TOP 1 возвращает первую запись из результирующих наборов. В совокупности этот запрос возвращает значения столбца CategoryID и CategoryName из одной случайно выбранной категории.

Чтобы отобразить значение категории CategoryName , добавьте элемент управления Label Web на страницу, задайте для его ID свойства CategoryNameLabelзначение и очистите его Text свойство. Чтобы программным способом получить данные из элемента управления SqlDataSource, необходимо вызвать его Select() метод . МетодSelect() ожидает один входной параметр типа DataSourceSelectArguments, который указывает способ отправки данных перед возвратом. Это может включать инструкции по сортировке и фильтрации данных и используется веб-элементами управления данными при сортировке или разбиении по страницам данных из элемента управления SqlDataSource. В нашем примере, однако, нам не нужно изменять данные перед возвратом, и поэтому мы будем передавать объект DataSourceSelectArguments.Empty .

Метод Select() возвращает объект , реализующий IEnumerable. Точный возвращаемый тип зависит от значения свойства элемента управления DataSourceModeSqlDataSource. Как обсуждалось в предыдущем руководстве, этому свойству можно задать значение DataSet или DataReader. Если задано значение DataSet, Select() метод возвращает объект DataView ; если задано значение DataReader, он возвращает объект , реализующий IDataReader. RandomCategoryDataSource Так как свойство SqlDataSource имеет DataSourceMode значение DataSet (по умолчанию), мы будем работать с объектом DataView.

В следующем коде показано, как получить записи из RandomCategoryDataSource SqlDataSource в виде DataView, а также как считывать CategoryName значение столбца из первой строки DataView:

protected void Page_Load(object sender, EventArgs e)
{
    // Get the data from the SqlDataSource as a DataView
    DataView randomCategoryView =
        (DataView)RandomCategoryDataSource.Select(DataSourceSelectArguments.Empty);
    if (randomCategoryView.Count > 0)
    {
        // Assign the CategoryName value to the Label
        CategoryNameLabel.Text =
            string.Format("Here are Products in the {0} Category...",
                randomCategoryView[0]["CategoryName"].ToString());
    }
}

randomCategoryView[0] возвращает первый DataRowView объект в DataView. randomCategoryView[0]["CategoryName"] возвращает значение столбца CategoryName в этой первой строке. Обратите внимание, что DataView имеет свободный тип. Чтобы сослаться на определенное значение столбца, необходимо передать имя столбца в виде строки (в данном случае CategoryName). На рисунке 13 показано сообщение, отображаемое в при CategoryNameLabel просмотре страницы. Конечно, фактическое отображаемое имя категории выбирается sqlDataSource случайным RandomCategoryDataSource образом при каждом посещении страницы (включая обратные передачи).

Отображается имя случайно выбранной категории

Рис. 13. Отображается имя случайно выбранной категории (щелкните для просмотра полноразмерного изображения)

Примечание

Если свойству элемента управления DataSourceMode SqlDataSource присвоено значение DataReader, возвращаемое из метода значение Select() должно быть приведено к IDataReader. Чтобы прочитать значение столбца CategoryName из первой строки, мы будем использовать следующий код:

if (randomCategoryReader.Read())
{
   string categoryName = randomCategoryReader["CategoryName"].ToString();
   ...
}

Когда SqlDataSource случайным образом выбирает категорию, мы готовимся к добавлению GridView, который выводит список продуктов категории.

Примечание

Вместо того, чтобы использовать веб-элемент управления Метки для отображения имени категории, мы могли бы добавить FormView или DetailsView на страницу, привязав их к SqlDataSource. Однако использование Label позволило изучить, как программно вызвать инструкцию SqlDataSource Select() и работать с полученными данными в коде.

Шаг 5. Назначение значений параметров программным способом

Во всех примерах, которые мы видели в этом руководстве, используется либо жестко закодированное значение параметра, либо значение, взятое из одного из предварительно определенных источников параметров (значение строки запроса, веб-элемент управления на странице и т. д.). Однако параметры элемента управления SqlDataSource также можно задать программным способом. Чтобы завершить текущий пример, нам нужен SqlDataSource, который возвращает все продукты, относящиеся к указанной категории. Этот sqlDataSource будет иметь CategoryID параметр, значение которого необходимо задать на CategoryID основе значения столбца, возвращаемого RandomCategoryDataSource SqlDataSource в обработчике Page_Load событий.

Сначала добавьте GridView на страницу и привяжите его к новому объекту SqlDataSource с именем ProductsByCategoryDataSource. Как и на шаге 3, настройте SqlDataSource таким образом, чтобы он вызвал хранимую GetProductsByCategory процедуру. Оставьте для раскрывающегося списка Источник параметров значение Нет, но не вводите значение по умолчанию, так как мы задаем это значение по умолчанию программным способом.

Снимок экрана: окно

Рис. 14. Не указывать источник параметров или значение по умолчанию (щелкните для просмотра полноразмерного изображения)

После завершения работы мастера SqlDataSource итоговая декларативная разметка должна выглядеть примерно так:

<asp:SqlDataSource ID="ProductsByCategoryDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="GetProductsByCategory" SelectCommandType="StoredProcedure">
    <SelectParameters>
        <asp:Parameter Name="CategoryID" Type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

Можно назначить DefaultValueCategoryID параметр программно в обработчике Page_Load событий:

// Assign the ProductsByCategoryDataSource's
// CategoryID parameter's DefaultValue property
ProductsByCategoryDataSource.SelectParameters["CategoryID"].DefaultValue =
    randomCategoryView[0]["CategoryID"].ToString();

С этим дополнением страница содержит Элемент GridView, в который отображаются продукты, связанные со случайно выбранной категорией.

Снимок экрана: страница

Рис. 15. Не указывать источник параметров или значение по умолчанию (щелкните для просмотра полноразмерного изображения)

Сводка

SqlDataSource позволяет разработчикам страниц определять параметризованные запросы, значения параметров которых могут быть жестко закодированы, извлечены из предварительно определенных источников параметров или назначены программным способом. В этом руководстве мы узнали, как создать параметризованный запрос из мастера настройки источника данных для нерегламентированных SQL-запросов и хранимых процедур. Мы также рассмотрели использование жестко заданных источников параметров, веб-элемента управления в качестве источника параметров и программного указания значения параметра.

Как и в случае с ObjectDataSource, SqlDataSource также предоставляет возможности для изменения базовых данных. В следующем руководстве мы рассмотрим, как определить INSERTоператоры , UPDATEи DELETE с помощью SqlDataSource. После добавления этих инструкций можно использовать встроенные функции вставки, редактирования и удаления, присущие элементам управления GridView, DetailsView и FormView.

Счастливое программирование!

Об авторе

Скотт Митчелл (Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с Веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часа. Его можно связать по адресу mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.

Отдельная благодарность

Эта серия учебников была проверена многими полезными рецензентами. В этом руководстве были ведущие рецензенты Скотт Клайд, Рэнделл Шмидт и Кен Песписа. Хотите ознакомиться с моими предстоящими статьями MSDN? Если да, опустите мне строку в mitchell@4GuysFromRolla.com.