Поделиться через


Использование Entity Framework 4.0 и элемента управления ObjectDataSource, часть 3. Сортировка и фильтрация

Том Дайкстра

Эта серия руководств основана на веб-приложении Университета Contoso, созданном начало работы с серией учебников По Entity Framework 4.0. Если вы не выполнили предыдущие руководства, в качестве отправной точки для этого руководства можно скачать созданное приложение . Вы также можете скачать приложение , созданное в полной серии учебников. Если у вас есть вопросы по этим руководствам, вы можете опубликовать их на форуме ASP.NET Entity Framework.

В предыдущем руководстве вы реализовали шаблон репозитория в n-уровневом веб-приложении, которое использует Entity Framework и ObjectDataSource элемент управления . В этом руководстве показано, как выполнять сортировку и фильтрацию, а также обрабатывать сценарии master детализации. Вы добавите следующие улучшения на страницу Departments.aspx :

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

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

Добавление возможности сортировки столбцов GridView

Откройте страницу Departments.aspx и добавьте SortParameterName="sortExpression" атрибут в ObjectDataSource элемент управления с именем DepartmentsObjectDataSource. (Позже вы создадите GetDepartments метод, который принимает параметр с именем sortExpression.) Разметка для открывающего тега элемента управления теперь похожа на следующий пример.

<asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.BLL.SchoolBL" DataObjectTypeName="ContosoUniversity.DAL.Department" 
        SelectMethod="GetDepartments" DeleteMethod="DeleteDepartment" UpdateMethod="UpdateDepartment"
        ConflictDetection="CompareAllValues" OldValuesParameterFormatString="orig{0}" 
        OnUpdated="DepartmentsObjectDataSource_Updated" SortParameterName="sortExpression" >

AllowSorting="true" Добавьте атрибут в открывающий тег GridView элемента управления . Разметка для открывающего тега элемента управления теперь похожа на следующий пример.

<asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource" DataKeyNames="DepartmentID" 
        OnRowUpdating="DepartmentsGridView_RowUpdating"
        AllowSorting="true" >

В файле Departments.aspx.cs задайте порядок сортировки по умолчанию, вызвав GridView метод элемента управления Sort из Page_Load метода :

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        DepartmentsGridView.Sort("Name", SortDirection.Ascending);
    }
}

Вы можете добавить код, который сортирует или фильтрует класс бизнес-логики или класс репозитория. Если это сделать в классе бизнес-логики, сортировка или фильтрация будет выполнена после извлечения данных из базы данных, так как класс бизнес-логики работает с IEnumerable объектом, возвращенным репозиторием. Если вы добавляете код сортировки и фильтрации в класс репозитория и выполняете это до преобразования выражения LINQ или запроса объекта в IEnumerable объект, команды будут переданы в базу данных для обработки, что обычно более эффективно. В этом руководстве вы реализуете сортировку и фильтрацию таким образом, чтобы обработка выполнялись базой данных, то есть в репозитории.

Чтобы добавить возможность сортировки, необходимо добавить новый метод в интерфейс репозитория и классы репозитория, а также в класс бизнес-логики. В файле ISchoolRepository.cs добавьте новый GetDepartments метод, который принимает sortExpression параметр , который будет использоваться для сортировки списка возвращенных отделов:

IEnumerable<Department> GetDepartments(string sortExpression);

Параметр sortExpression задает столбец для сортировки и направление сортировки.

Добавьте код для нового метода в файл SchoolRepository.cs :

public IEnumerable<Department> GetDepartments(string sortExpression)
{
    if (String.IsNullOrWhiteSpace(sortExpression))
    {
        sortExpression = "Name";
    }
    return context.Departments.Include("Person").OrderBy("it." + sortExpression).ToList();
}

Измените существующий метод без GetDepartments параметров, чтобы вызвать новый метод:

public IEnumerable<Department> GetDepartments()
{
    return GetDepartments("");
}

В тестовом проекте добавьте следующий новый метод в файл MockSchoolRepository.cs:

public IEnumerable<Department> GetDepartments(string sortExpression)
{
    return departments;
}

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

В файле SchoolBL.cs добавьте следующий новый метод в класс бизнес-логики:

public IEnumerable<Department> GetDepartments(string sortExpression)
{
    return schoolRepository.GetDepartments(sortExpression);
}

Этот код передает параметр сортировки методу репозитория.

Запустите страницу Departments.aspx .

Image02

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

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

Откройте страницу Departments.aspx и добавьте следующую разметку между заголовком и первым ObjectDataSource элементом управления:

Enter any part of the name or leave the box blank to see all names:
    <asp:TextBox ID="SearchTextBox" runat="server" AutoPostBack="true"></asp:TextBox>
     <asp:Button ID="SearchButton" runat="server" Text="Search" />

В элементе ObjectDataSource управления с именем DepartmentsObjectDataSourceсделайте следующее:

  • SelectParameters Добавьте элемент для параметра с именем nameSearchString , который получает значение, введенное в элементе SearchTextBox управления .
  • Измените значение атрибута SelectMethod на GetDepartmentsByName. (Этот метод будет создан позже.)

Разметка для элемента управления теперь похожа ObjectDataSource на следующий пример:

<asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" TypeName="ContosoUniversity.BLL.SchoolBL"
        SelectMethod="GetDepartmentsByName" DeleteMethod="DeleteDepartment" UpdateMethod="UpdateDepartment"
        DataObjectTypeName="ContosoUniversity.DAL.Department" ConflictDetection="CompareAllValues"
        SortParameterName="sortExpression" OldValuesParameterFormatString="orig{0}" 
        OnUpdated="DepartmentsObjectDataSource_Updated">
        <SelectParameters>
            <asp:ControlParameter ControlID="SearchTextBox" Name="nameSearchString" PropertyName="Text"
                Type="String" />
        </SelectParameters>
    </asp:ObjectDataSource>

В файле ISchoolRepository.cs добавьте GetDepartmentsByName метод , который принимает параметры sortExpression и nameSearchString :

IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString);

В файле SchoolRepository.cs добавьте следующий новый метод:

public IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString)
{
    if (String.IsNullOrWhiteSpace(sortExpression))
    {
        sortExpression = "Name";
    }
    if (String.IsNullOrWhiteSpace(nameSearchString))
    {
        nameSearchString = "";
    }
    return context.Departments.Include("Person").OrderBy("it." + sortExpression).Where(d => d.Name.Contains(nameSearchString)).ToList();
}

Этот код использует метод для Where выбора элементов, содержащих строку поиска. Если строка поиска пуста, будут выбраны все записи. Обратите внимание, что при совместном указании вызовов метода в одном операторе, как это (Include, затем OrderBy, то Where), Where метод всегда должен быть последним.

Измените существующий GetDepartments метод, который принимает sortExpression параметр, чтобы вызвать новый метод:

public IEnumerable<Department> GetDepartments(string sortExpression)
{
    return GetDepartmentsByName(sortExpression, "");
}

В файле MockSchoolRepository.cs в тестовом проекте добавьте следующий новый метод:

public IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString)
{
    return departments;
}

В SchoolBL.cs добавьте следующий новый метод:

public IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString)
{
    return schoolRepository.GetDepartmentsByName(sortExpression, nameSearchString);
}

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

Image03

Добавление столбца сведений для каждой строки сетки

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

Откройте Файл Departments.aspx и в разметке GridView для элемента управления укажите обработчик для RowDataBound события. Разметка для открывающего тега элемента управления теперь похожа на следующий пример.

<asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource" DataKeyNames="DepartmentID" 
        OnRowUpdating="DepartmentsGridView_RowUpdating"
        OnRowDataBound="DepartmentsGridView_RowDataBound"
        AllowSorting="True" >

Добавьте новый TemplateField элемент после Administrator поля шаблона:

<asp:TemplateField HeaderText="Courses">
                <ItemTemplate>
                    <asp:GridView ID="CoursesGridView" runat="server" AutoGenerateColumns="False">
                        <Columns>
                            <asp:BoundField DataField="CourseID" HeaderText="ID" />
                            <asp:BoundField DataField="Title" HeaderText="Title" />
                        </Columns>
                    </asp:GridView>
                </ItemTemplate>
            </asp:TemplateField>

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

Откройте файл Departments.aspx.cs и добавьте следующий обработчик для RowDataBound события:

protected void DepartmentsGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        var department = e.Row.DataItem as Department;
        var coursesGridView = (GridView)e.Row.FindControl("CoursesGridView");
        coursesGridView.DataSource = department.Courses.ToList();
        coursesGridView.DataBind();
    }
}

Этот код получает Department сущность из аргументов события, преобразует свойство навигации Courses в коллекцию List и привязывает вложенный GridView объект к коллекции.

Откройте файл SchoolRepository.cs и укажите неотложную загрузку для Courses свойства навигации, вызвав Include метод в запросе объекта, созданном в методе GetDepartmentsByName . Оператор return в методе GetDepartmentsByName теперь похож на следующий пример.

return context.Departments.Include("Person").Include("Courses").
    OrderBy("it." + sortExpression).Where(d => d.Name.Contains(nameSearchString)).ToList();

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

Снимок экрана: элемент управления

На этом мы завершаем общие сведения о сценариях сортировки, фильтрации и master подробных сведений. В следующем руководстве вы узнаете, как обрабатывать параллелизм.