• Microsoft .NET
  • ASP.NET
  • Периодическое обновление экрана и заголовка веб-страницы при помощи ASP.NET AJAX

Доступ к данным с помощью элементов управления источником данных (DataSource) в ASP.NET 2.0 - Выборка товаров, у которых значение CategoryID равно NULL

ОГЛАВЛЕНИЕ

Выборка товаров, у которых значение CategoryID равно NULL

Элемент SqlDataSource, используемый в статье "Модификация интерфейса редактирования", возвращает данные о товарах из таблицы Products, включая соответствующее название категории из таблицы Categories. Это было выполнено посредством следующего  выражения SelectCommand:

SELECT [ProductID], [ProductName], [Products].[CategoryID], 
       [CategoryName], [UnitPrice], [Discontinued]
FROM [Products]
       INNER JOIN [Categories] ON
              [Products].[CategoryID] = [Categories].[CategoryID]
ORDER BY [ProductName]

INNER JOIN возвращает совпавшие строки Categories , что позволяет нам получать CategoryName для товаров связанных со значением CategoryID.

Колонка CategoryID таблицы Products может содержать пустые значения (NULL), но INNER JOINs пропускают строки, где имеются пустые поля по объединенной колонке. Вкратце, INNER JOIN , используемое в предыдущем запросе, возвращает только те товары, которые имеют не пустое значение CategoryID . Для того, чтобы вернуть все товары, независимо от того имеют ли они значение NULL в CategoryID, нам нужно использовать LEFT JOIN.

SELECT [ProductID], [ProductName], [Products].[CategoryID], 
       [CategoryName], [UnitPrice], [Discontinued]
FROM [Products]
       LEFT JOIN [Categories] ON
              [Products].[CategoryID] = [Categories].[CategoryID]
ORDER BY [ProductName]

Изменив синтаксис объединения JOIN на LEFT JOIN, мы получим табличную сетку, включающую в себя и те товары, у которых значение CategoryID равно NULL. По умолчанию, значения NULL отображаются в виде пустой строки в ItemTemplate. К примеру, следующее изображение показывает товар Boston Crab Meat, у которого значение CategoryID равно NULL, и, как это заметно, отображено оно в виде пустой строки в колонке Category Name.


Изменение к левому объединению (Left Join) является всего лишь первым шагом. Нам также необходимо обновить CategoriesDDL DropDownList в интерфейсе редактирования колонки Category Name. На данный момент CategoriesDDL привязан к набору категорий в таблице Categories. То есть, нет ни одной записи, которая соответствовала бы значению NULL в базе данных. Следовательно, если мы попытаемся отредактировать товар, у которого значение CategoryID равно NULL, то мы получим ошибку. Ошибка произойдет потому, что в EditItemTemplate мы привязываем значение CategoryID редактируемого товара к свойству SelectedValue элемента CategoriesDDL DropDownList,  в то  время как CategoriesDDL DropDownList не имеет такого значения.


Модифицируем элемент управления CategoriesDDL DropDownList так, чтобы он мог обрабатывать значения NULL

Нам необходимо обновить список элементов в CategoriesDDL DropDownList таким образом, чтобы он включал в себя полный набор возможных категорий, а также элемент, соответствующий значению NULL базы данных. Объекты Parameter в SqlDataSource (либо ObjectDataSource), сами  преобразят значения NULL в пустые строки и обратно. Тем самым все, что нам надо сделать для того, чтобы все это получилось - добавить в список CategoriesDDL DropDownList элемент, который имеет значение пустой строки.

Как только мы внесем пустую строку как элемент списка в CategoriesDDL DropDownList, двусторонняя привязка данных будет работать идеально. Когда строку, у которой CategoryID равно NULL, будет редактироваться, значение NULL будет преобразовано в пустую строку и соответствующий элемент выпадающего списка будет выбран. Аналогично, если в списке будет выбрана пустая строка и затем она будет передана в базу данных, то в результате будет сохранено значение NULL.

Для того чтобы добавить элемент в список DropDownList со значением пустой строки нам необходимо сделать две вещи :

  1. Установить свойство AppendDataBoundItems элемента DropDownList в True.
  2. Добавить <asp:ListItem> к декларативной разметке элемента, установить Value="".

После того, как мы применим все эти действия, разметка Category Name TemplateField будет выглядеть следующим образом:

<asp:TemplateField HeaderText="CategoryName" SortExpression="CategoryName">
    <EditItemTemplate>
       <asp:DropDownList ID="CategoriesDDL" runat="server" DataSourceID="CategoriesDataSource" AppendDataBoundItems="True"
            DataTextField="CategoryName" DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'>
                <asp:ListItem Text="(None)" Value=""></asp:ListItem>
       </asp:DropDownList>


       <asp:SqlDataSource ID="CategoriesDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
            SelectCommand="SELECT [CategoryID], [CategoryName] FROM [Categories] ORDER BY [CategoryName]">
       </asp:SqlDataSource>
    </EditItemTemplate>
    <ItemTemplate>
       <asp:Label ID="Label2" runat="server" Text='<%# Bind("CategoryName") %>'></asp:Label>
    </ItemTemplate>
</asp:TemplateField>

Разметка, добавленная согласно двум указанным шагам, отмечена красным цветом. Обратите внимание на установление свойства AppendDataBoundItems. Если свойство AppendDataBoundItems установлено в False (по умолчанию), то категории, привязанные к DropDownList при помощи SqlDataSource в EditItemTemplate перепишут элемент списка для значения NULL базы данных.

Второй шаг вручную добавляет элемент к списку DropDownList. Свойству Text элемента списка можно присвоить любое значение (здесь мы используем "(None)"), но важно помнить, что свойство Value может быть явно установлено в пустую строку. То есть, обязательным условием является то, что разметка ListItem включает в себя Value="". Если вы опустите данное условие, то свойство Value возвратит то же самое значение, что хранится в свойстве Text. Также предупреждаю вас о том, что свойство Value не может быть приравнено к пустой строке посредством дизайнера (Designer). Попытка просто напросто пропустит свойство Value в декларативном синтаксисе. Вы должны ввести данную разметку через декларативный синтаксис.

На данный момент GridView позволяет отображать товары со значением NULL в CategoryID и позволяет редактировать такие товары, а также назначать значение NULL категории товара.