Использование 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 .
Теперь можно щелкнуть любой заголовок столбца для сортировки по столбцу. Если столбец уже отсортирован, щелчок заголовка меняет направление сортировки.
Добавление поля поиска
В этом разделе вы добавите текстовое поле поиска, свяжете его с 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 и введите строку поиска, чтобы убедиться, что логика выбора работает. Оставьте текстовое поле пустым и попробуйте выполнить поиск, чтобы убедиться, что возвращаются все записи.
Добавление столбца сведений для каждой строки сетки
Затем вы хотите просмотреть все курсы для каждого отдела, отображаемые в правой ячейке сетки. Для этого вы будете использовать вложенный 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 подробных сведений. В следующем руководстве вы узнаете, как обрабатывать параллелизм.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по