| Россия, г. Санкт-Петербург |
Обеспечение взаимодействия Интернет-магазина с базой данных
11.2. Доработка страницы продуктов с использованием LINQ to SQL
После того, как разработано меню, позволяющее ограничивать категорию товара, которой интересуется пользователь, необходимо переработать страницу продуктов так, чтобы она извлекала сведения о продуктах из базы данных, и могла их ограничивать по категориям.
Для доступа к данным мы воспользуемся другой технологией, входящей в состав .NET Framework – LINQ to SQL. Эта технология позволяет извлекать данные из БД в виде связанных объектов, которые более привычны разработчику, программирующем на объекто-ориентированных языках программирования, и позволяет использовать язык интегрированных запросов LINQ для манипуляций с этими объектами.
Для того, чтобы добавить отображение таблиц данных в виде LINQ to SQL в проект, необходимо кликнуть правой клавишей мыши по папке App_Data, в контекстном меню выбрать пункт Add New Item. В открывшемся диалоговом окне ненужно выбрать элемент LINQ to SQL Classes (рис. 11.5).
После добавление классов в проект, откроется дизайнер классов (рис. 11.6). Добавим в него таблицы ProductCategory, ProductSubcategory, ProductModel, ProductModelIllustrtions, Product, ProductDescriptions, ProductModelProductDescriptionCulture, ProductPhoto, ProductProductPhoto и Productreview, перетащив их мышкой из окна Server Explorer.
Прежде чем приступить к дальнейшей работе, откроем файл DataClasses.designer.cs и увидим сгенерированный код для классов. Перейдем в класс Product и добавим в него следующий код:
public string FullSize
{
get
{
return Size + " " + SizeUnitMeasureCode;
}
}Теперь мы определили собственное свойство у объекта product, которое отображает его размер с указанными единицами измерений. Стоит отметить, что это свойство вычислимое, оно не хранится в БД и его нельзя изменить.
Теперь перейдем к странице products/default.aspx и переопределим код левого PlaceHolder' а. прежде всего, добавим в него определение нового источника данных – LinqDataSource. Это можно сделать, набрав код руками, а можно перетащить соответствующий элемент из окна Toolbox и настроить его в специальном мастере. Так или иначе, должен получиться следующий код:
<asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="DataClassesDataContext" Select="new (ProductID, Name, ProductNumber, Color, ListPrice, Size, SizeUnitMeasureCode, WeightUnitMeasureCode, Weight, FullSize)" TableName="Product"> </asp:LinqDataSource>
В источнике данных LinqDataSource указано, что необходимо брать объекты типа Products, определенные в DataClassesDataContext, и предоставлять доступ компонентам, которые будут использовать этот источник данных только к тем свойствам, которые указаны в атрибуте Select. Теперь переопределим GridView так, чтобы он использовал новый источник данных:
<asp:GridView ID="GridViewProducts" runat="server" CellPadding="4"
GridLines="None" CssClass="GridViewProduct"
AllowSorting="True" AutoGenerateColumns="False"
AllowPaging="True" DataSourceID="LinqDataSource1"
OnSelectedIndexChanged="OnSelectedIndexChanged" >
<RowStyle CssClass="tr_nechet" />
<AlternatingRowStyle CssClass="tr_chet" />
<Columns>
<asp:CommandField SelectText="Выбор" ShowSelectButton="True" />
<asp:BoundField DataField="ProductID" HeaderText="ProductID"
ReadOnly="True"
SortExpression="ProductID" Visible="False" />
<asp:BoundField DataField="ProductNumber" HeaderText="Номер продукта"
ReadOnly="True" SortExpression="ProductNumber" />
<asp:BoundField DataField="Name" HeaderText="Название" ReadOnly="True"
SortExpression="Name" />
<asp:BoundField DataField="Color" HeaderText="Цвет" ReadOnly="True"
SortExpression="Color" />
<asp:BoundField DataField="ListPrice" HeaderText="Цена" ReadOnly="True"
SortExpression="ListPrice" NullDisplayText="Цена не указана"
DataFormatString="{0:F2}" />
<asp:BoundField DataField="FullSize" HeaderText="Размер" ReadOnly="True"
SortExpression="FullSize" />
<asp:TemplateField HeaderText="Вес" SortExpression="Weight" >
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Eval("Weight") + " " + Eval("WeightUnitMeasureCode") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />
<SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" />
<HeaderStyle CssClass="tr_main" />
</asp:GridView>Здесь стоит обратить внимание на то, что для GridView установлен источник данных ( DataSourceID="LinqDataSource1" ), разрешены операции сортировки и постраничного вывода ( AllowSorting="True" и AllowPaging="True" ). При этом изменилось и определение колонок – теперь мы можем использовать BoundField, в которых при помощи атрибута DataField указать, какое свойство необходимо отображать. Также, для свойства ListPrice, определяющего цену на товар задан формат вывода ( DataFormatString="{0:F2}" ), который определяет, что строку надо выводить как число с двумя знаками после запятой. Также, для примера, GridView содержит один столбец, использующий TemplateField, который отображает вес товара вместе с единицей измерения веса. Это альтернативный способ добиться отображения сложных полей (для этих же целей мы определили свойство FullSize ).
Теперь необходимо изменить метод Page_Load. В нем нам необходимо ввести ограничения на извлекаемые данные, ограничив категорию и подкатегорию продуктов. Для этого у объектов LinqDataSource есть свойства Where и WhereParameters. При нажатии на определенный пункт меню, происходит переадресация на страницу products/default.aspx, при этом категория и подкатегория передаются через параметры category и subCategory. Прежде всего, необходимо сбросить текущие фильтры, после чего, если определена подкатегория (это можно узнать, проверив содержимое Request.QueryString["subCategory"] ) то достаточно указать свойство Where = "ProductSubcategoryID == @subCategory", а в коллекцию WhereParameters добавить новый параметр "subCategory" со значением, переданным в строке запроса – Request.QueryString["subCategory"]. Если же подкатегория не была указана, но была указана категория, то свойству where необходимо присвоить значение "ProductSubcategory.ProductCategoryID == @category" и задать параметр category в WhereParameters.
Ниже приведен полный код метода Page_Load.
protected void Page_Load(object sender, EventArgs e)
{
GridViewProducts.DataKeyNames = new string[]
{
"ProductID"
};
LinqDataSource1.Where = "";
LinqDataSource1.WhereParameters.Clear();
if (!string.IsNullOrEmpty(Request.QueryString["subCategory"]))
{
LinqDataSource1.Where = "ProductSubcategoryID == @subCategory";
LinqDataSource1.WhereParameters.Add("subCategory", DbType.Int32, Request.QueryString["subCategory"]);
}
else
{
if (!string.IsNullOrEmpty(Request.QueryString["category"]))
{
LinqDataSource1.Where = "ProductSubcategory.ProductCategoryID == @category";
LinqDataSource1.WhereParameters.Add("category", DbType.Int32, Request.QueryString["category"]);
}
}
}На рис. 11.7 представлен вид страницы продуктов при выбранном пункте меню "Mountain Bikes".


