Начало работы с базой данных Entity Framework 4.0 First и ASP.NET 4 Web Forms — часть 3

Том Дайкстра

Пример веб-приложения Contoso University наглядно показывает, как создавать приложения ASP.NET Web Forms с помощью Entity Framework 4.0 и Visual Studio 2010. Для информации о серии учебных руководств см. первый учебник этой серии

Фильтрация, упорядочивание и группирование данных

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

Вы измените страницу Students.aspx , чтобы отфильтровать учащихся, отсортировать по имени и выполнить поиск по имени. Вы также измените страницу Courses.aspx , чтобы отобразить курсы для выбранного отдела и найти курсы по имени. Наконец, вы добавите статистику учащихся на страницу About.aspx .

Снимок экрана: окно Internet Explorer, показывающее представление списка учащихся с таблицей учащихся.

Снимок экрана окна Internet Explorer, показывающего курсы по отделам и по названиям.

Снимок экрана: окно Internet Explorer, показывающее представление статистики тела учащихся с таблицей дат регистрации.

Снимок экрана: окно Internet Explorer, показывающее представление

Использование свойства EntityDataSource Where для фильтрации данных

Откройте страницу Students.aspx , созданную в предыдущем руководстве. В настоящее время элемент GridView управления на странице отображает все имена из People набора сущностей. Однако вы хотите показать только учащихся, которых можно найти, выбрав Person сущности с ненулевыми датами регистрации.

Переключитесь в режим 'Конструктор' и выберите EntityDataSource элемент управления. В окне свойств задайте для свойства Where значение it.EnrollmentDate is not null.

Image01

Синтаксис, используемый в свойстве WhereEntityDataSource элемента управления, — Entity SQL. Entity SQL похож на Transact-SQL, но он настраивается для использования с сущностями, а не объектами базы данных. В выражении it.EnrollmentDate is not nullслово it представляет ссылку на сущность, возвращаемую запросом. it.EnrollmentDate относится к свойству EnrollmentDate сущности Person, которую возвращает элемент управления EntityDataSource.

Запустите страницу. Список студентов теперь содержит только студентов. (Строки не отображаются, где нет даты регистрации.)

Снимок экрана: окно Internet Explorer, в котором отображается представление списка учащихся с таблицей учащихся.

Использование свойства EntityDataSource "OrderBy" для заказа данных

Вы также хотите, чтобы этот список был в порядке имени при первом отображении. Если страница Students.aspx по-прежнему открыта в режиме конструктора , а элемент EntityDataSource управления по-прежнему выбран, в окне "Свойства " задайте для свойства OrderBy значение it.LastName.

Image05

Запустите страницу. Список учащихся теперь упорядочен по фамилии.

Image04

Использование параметра элемента управления для задания свойства "Where"

Как и в случае с другими элементами управления источниками данных, можно передать значения параметров свойству Where . На странице Courses.aspx , созданной в части 2 руководства, этот метод можно использовать для отображения курсов, связанных с отделом, который пользователь выбирает из раскрывающегося списка.

Откройте Courses.aspx и перейдите в режим конструктора . Добавьте второй EntityDataSource элемент управления на страницу и назовите его CoursesEntityDataSource. Подключите его к SchoolEntities модели, и выберите Courses в качестве значения EntitySetName.

В окне "Свойства" щелкните многоточие в поле " Где ". (Убедитесь, что CoursesEntityDataSource элемент управления по-прежнему выбран перед использованием окна "Свойства ".)

Image06

Откроется диалоговое окно редактора выражений . В этом диалоговом окне выберите "Автоматически создать выражение Where на основе предоставленных параметров", а затем нажмите кнопку "Добавить параметр". Присвойте параметру имя DepartmentID, выберите Control в качестве значения источника параметра и выберите DepartmentsDropDownList в качестве значения ControlID.

Image07

Нажмите кнопку "Показать дополнительные свойства" и в окне "Свойства" диалогового окна редактора выражений измените свойство Typeна Int32 .

Image15

По завершении нажмите кнопку "ОК".

Под раскрывающимся списком добавьте элемент управления GridView на страницу и назовите его CoursesGridView. Подключите его к элементу CoursesEntityDataSource управления источниками данных, нажмите кнопку "Обновить схему", щелкните " Изменить столбцы" и удалите DepartmentID столбец. Разметка GridView элемента управления похожа на следующий пример.

<asp:GridView ID="CoursesGridView" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="CourseID" DataSourceID="CoursesEntityDataSource">
        <Columns>
            <asp:BoundField DataField="CourseID" HeaderText="ID" ReadOnly="True" 
                SortExpression="CourseID" />
            <asp:BoundField DataField="Title" HeaderText="Title" SortExpression="Title" />
            <asp:BoundField DataField="Credits" HeaderText="Credits" 
                SortExpression="Credits" />
        </Columns>
    </asp:GridView>

Когда пользователь изменяет выбранный отдел в раскрывающемся списке, необходимо автоматически изменить список связанных курсов. Чтобы это сделать, выберите раскрывающийся список, и в окне Свойства установите для свойства AutoPostBack значение True.

Image08

Теперь, когда вы завершили работу в конструкторе, перейдите в представление источника и замените свойства ConnectionString и DefaultContainer, а также имя CoursesEntityDataSource элемента управления атрибутом ContextTypeName="ContosoUniversity.DAL.SchoolEntities". По завершении разметка элемента управления будет выглядеть следующим образом.

<asp:EntityDataSource ID="CoursesEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="false"
        EntitySetName="Courses" 
        AutoGenerateWhereClause="true" Where="">
        <WhereParameters>
            <asp:ControlParameter ControlID="DepartmentsDropDownList" Type="Int32" 
                Name="DepartmentID" PropertyName="SelectedValue" />
        </WhereParameters>
    </asp:EntityDataSource>

Запустите страницу и используйте раскрывающийся список для выбора разных отделов. В элементе GridView управления отображаются только курсы, предлагаемые выбранным отделом.

Image09

Использование свойства EntityDataSource "GroupBy" для группирования данных

Предположим, что Университет Contoso хочет разместить на странице "О нас" статистику по студентам. В частности, он хочет показать разбивку числа учащихся по дате их регистрации.

Откройте About.aspx и в режиме исходного кода замените существующее содержимое элемента управления BodyContent на "Статистика контингента учащихся" между h2 тегами.

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <h2>Student Body Statistics</h2>
</asp:Content>

После заголовка добавьте EntityDataSource элемент управления и назовите его StudentStatisticsEntityDataSource. Подключите его к SchoolEntities, выберите People набор сущностей и оставьте поле "Выбрать " в мастере без изменений. Задайте следующие свойства в окне свойств :

  • Чтобы отфильтровать только учащихся, задайте значение it.EnrollmentDate is not null для свойства Where.
  • Чтобы сгруппировать результаты по дате регистрации, задайте свойству it.EnrollmentDate значение GroupBy.
  • Чтобы выбрать дату регистрации и число учащихся, установите значение свойства Select на it.EnrollmentDate, Count(it.EnrollmentDate) AS NumberOfStudents.
  • Чтобы упорядочить результаты по дате регистрации, установите свойство OrderBy на it.EnrollmentDate.

В представлении источника замените имя свойства для ConnectionString и DefaultContainer на свойство ContextTypeName. Разметка EntityDataSource элемента управления теперь похожа на следующий пример.

<asp:EntityDataSource ID="StudentStatisticsEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" 
        EntitySetName="People"
        Select="it.EnrollmentDate, Count(it.EnrollmentDate) AS NumberOfStudents" 
        OrderBy="it.EnrollmentDate" GroupBy="it.EnrollmentDate"
        Where="it.EnrollmentDate is not null" >
    </asp:EntityDataSource>

Синтаксис свойств Select, GroupBy, и Where похож на Transact-SQL, за исключением ключевого слова it, указывающего текущую сущность.

Добавьте следующую GridView разметку, чтобы создать элемент управления для отображения данных.

<asp:GridView ID="StudentStatisticsGridView" runat="server" AutoGenerateColumns="False" 
        DataSourceID="StudentStatisticsEntityDataSource">
        <Columns>
            <asp:BoundField DataField="EnrollmentDate" DataFormatString="{0:d}" 
                HeaderText="Date of Enrollment" 
                ReadOnly="True" SortExpression="EnrollmentDate" />
            <asp:BoundField DataField="NumberOfStudents" HeaderText="Students" 
                ReadOnly="True" SortExpression="NumberOfStudents" />
        </Columns>
    </asp:GridView>

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

Снимок экрана: окно Internet Explorer, в котором отображается представление статистики тела учащихся с таблицей дат регистрации.

Использование элемента управления QueryExtender для фильтрации и упорядочивания

Элемент QueryExtender управления позволяет указать фильтрацию и сортировку в разметке. Синтаксис не зависит от используемой системы управления базами данных (СУБД). Это также обычно независимо от Entity Framework, за исключением того, что синтаксис, используемый для свойств навигации, является уникальным для Entity Framework.

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

(Если вы предпочитаете использовать код вместо разметки для расширения запросов, автоматически создаваемых EntityDataSource элементом управления, это можно сделать, обрабатывая QueryCreated событие. Таким образом, QueryExtender элемент управления расширяет EntityDataSource запросы элементов управления.)

Откройте страницу Courses.aspx и под разметкой, которую вы добавили ранее, вставьте следующую разметку, чтобы создать заголовок, текстовое поле для ввода строк поиска, кнопки поиска и EntityDataSource элемента управления, привязанного к набору Courses сущностей.

<h2>Courses by Name</h2>
    Enter a course name 
    <asp:TextBox ID="SearchTextBox" runat="server"></asp:TextBox>
     <asp:Button ID="SearchButton" runat="server" Text="Search" />
    <br /><br />
    <asp:EntityDataSource ID="SearchEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" 
        EntitySetName="Courses"  
        Include="Department" >
    </asp:EntityDataSource>

Обратите внимание, что свойству Include элемента управления EntityDataSource задано значение Department. В базе данных таблица Course не содержит имени отдела; она содержит столбец внешнего ключа DepartmentID. Если бы вы напрямую запрашивали базу данных, чтобы получить название отдела вместе с данными курсов, вам пришлось бы объединить таблицы Course и Department. При установке свойства Include в Department вы указываете, что Entity Framework должна выполнять задачу по получению связанной сущности Department при извлечении сущности Course. Затем сущность Department сохраняется в навигационном свойстве Department сущности Course. (По умолчанию класс, созданный конструктором моделей данных, SchoolEntities извлекает связанные данные при необходимости, и вы привязали управление источником данных к тому классу, поэтому установка Include свойства не требуется. Однако настройка повышает производительность страницы, так как в противном случае Entity Framework будет выполнять отдельные вызовы к базе данных для получения данных для Course сущностей и связанных Department сущностей.)

EntityDataSource После создания элемента управления вставьте следующую QueryExtender разметку, чтобы создать элемент управления, связанный с этим EntityDataSource элементом управления.

<asp:QueryExtender ID="SearchQueryExtender" runat="server" 
        TargetControlID="SearchEntityDataSource" >
        <asp:SearchExpression SearchType="StartsWith" DataFields="Title">
            <asp:ControlParameter ControlID="SearchTextBox" />
        </asp:SearchExpression>
        <asp:OrderByExpression DataField="Department.Name" Direction="Ascending">
            <asp:ThenBy DataField="Title" Direction="Ascending" />            
        </asp:OrderByExpression>
    </asp:QueryExtender>

Элемент SearchExpression указывает, что вы хотите выбрать курсы, названия которых соответствуют значению, введенное в текстовом поле. Сравниваются только столько символов, сколько введено в текстовом поле, так как SearchType свойство указывает StartsWith.

Элемент OrderByExpression указывает, что результирующий набор будет упорядочен по названию курса в имени отдела. Обратите внимание, как указано имя отдела: Department.Name Поскольку связь между сущностью Course и сущностью Department является один-к-одному, свойство навигации Department содержит сущность Department. (Если это была связь "один ко многим", свойство будет содержать коллекцию.) Чтобы получить имя отдела, необходимо указать свойство Name сущности Department.

Наконец, добавьте GridView элемент управления для отображения списка курсов:

<asp:GridView ID="SearchGridView" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="CourseID" DataSourceID="SearchEntityDataSource"  AllowPaging="true">
        <Columns>
            <asp:TemplateField HeaderText="Department">
                <ItemTemplate>
                    <asp:Label ID="Label2" runat="server" Text='<%# Eval("Department.Name") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="CourseID" HeaderText="ID"/>
            <asp:BoundField DataField="Title" HeaderText="Title" />
            <asp:BoundField DataField="Credits" HeaderText="Credits" />
        </Columns>
    </asp:GridView>

Первый столбец — это поле шаблона, отображающее имя отдела. Выражение привязки данных указывает Department.Name, так же как и в контроле QueryExtender.

Запустите страницу. Первоначальное отображение отображает список всех курсов по отделу, а затем по названию курса.

Снимок экрана: окно Internet Explorer, в котором показаны курсы по отделам и курсам по имени.

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

Image12

Использование оператора "Like" для фильтрации данных

Вы можете достичь эффекта, аналогичного типам поиска QueryExtender, StartsWith, Contains и EndsWith элементов управления, используя оператор Like в свойстве EntityDataSource элемента управления Where. В этой части руководства вы узнаете, как использовать Like оператор для поиска учащегося по имени.

Откройте Students.aspx в представлении источника . GridView После элемента управления добавьте следующую разметку:

<h2>Find Students by Name</h2>
    Enter any part of the name
    <asp:TextBox ID="SearchTextBox" runat="server" AutoPostBack="true"></asp:TextBox>
     <asp:Button ID="SearchButton" runat="server" Text="Search" />
    <br />
    <br />
    <asp:EntityDataSource ID="SearchEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" 
        EntitySetName="People"
        Where="it.EnrollmentDate is not null and (it.FirstMidName Like '%' + @StudentName + '%' or it.LastName Like '%' + @StudentName + '%')" >
        <WhereParameters>
            <asp:ControlParameter ControlID="SearchTextBox" Name="StudentName" PropertyName="Text" 
             Type="String" DefaultValue="%"/>
        </WhereParameters>
    </asp:EntityDataSource>
    <asp:GridView ID="SearchGridView" runat="server" AutoGenerateColumns="False" DataKeyNames="PersonID"
        DataSourceID="SearchEntityDataSource" AllowPaging="true">
        <Columns>
            <asp:TemplateField HeaderText="Name" SortExpression="LastName, FirstMidName">
                <ItemTemplate>
                    <asp:Label ID="LastNameFoundLabel" runat="server" Text='<%# Eval("LastName") %>'></asp:Label>, 
                    <asp:Label ID="FirstNameFoundLabel" runat="server" Text='<%# Eval("FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Enrollment Date" SortExpression="EnrollmentDate">
                <ItemTemplate>
                    <asp:Label ID="EnrollmentDateFoundLabel" runat="server" Text='<%# Eval("EnrollmentDate", "{0:d}") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

Эта разметка похожа на то, что вы видели ранее, кроме значения свойства Where. Вторая часть Where выражения определяет поиск подстроки (LIKE %FirstMidName% or LIKE %LastName%), который выполняет поиск в именах и фамилиях для любого текста, введенного в текстовое поле.

Запустите страницу. Первоначально все учащиеся отображаются, так как значение по умолчанию для StudentName параметра — "%".

Image13

Введите букву "g" в текстовом поле и нажмите кнопку "Поиск". Вы увидите список учащихся, в именах или фамилиях которых содержится буква "g".

Снимок экрана: окно Internet Explorer, в котором отображается представление

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