Учебник. Добавление сортировки, фильтрации и разбиения на страницы с помощью Entity Framework в приложении ASP.NET MVCTutorial: Add sorting, filtering, and paging with the Entity Framework in an ASP.NET MVC application

В предыдущем руководствевы реализовали набор веб-страниц для базовых операций CRUD для сущностей Student.In the previous tutorial, you implemented a set of web pages for basic CRUD operations for Student entities. В этом руководстве вы добавите функции сортировки, фильтрации и разбиения на страницы для индекса учащихся .In this tutorial you add sorting, filtering, and paging functionality to the Students Index page. Вы также создадите простую страницу группирования.You also create a simple grouping page.

На следующем рисунке показано, как будет выглядеть страница после завершения.The following image shows what the page will look like when you're done. Заголовки столбцов являются ссылками, при нажатии на которые происходит сортировка по этому столбцу.The column headings are links that the user can click to sort by that column. При повторном нажатии на заголовок происходит переключение между сортировкой по возрастанию и убыванию.Clicking a column heading repeatedly toggles between ascending and descending sort order.

Students_Index_page_with_paging

Изучив это руководство, вы:In this tutorial, you:

  • Добавление ссылок для сортировки столбцовAdd column sort links
  • Добавление поля поискаAdd a Search box
  • Добавление разбиения по страницамAdd paging
  • Создание страницы сведенийCreate an About page

предварительные требованияPrerequisites

Чтобы добавить сортировку на страницу индекса учащихся, измените метод Index контроллера Student и добавьте код в Student представление индекса.To add sorting to the Student Index page, you'll change the Index method of the Student controller and add code to the Student Index view.

Добавление функции сортировки в метод IndexAdd sorting functionality to the Index method

  • В контроллерс\студентконтроллер.КСзамените метод Index следующим кодом:In Controllers\StudentController.cs, replace the Index method with the following code:

    public ActionResult Index(string sortOrder)
    {
       ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
       ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
       var students = from s in db.Students
                      select s;
       switch (sortOrder)
       {
          case "name_desc":
             students = students.OrderByDescending(s => s.LastName);
             break;
          case "Date":
             students = students.OrderBy(s => s.EnrollmentDate);
             break;
          case "date_desc":
             students = students.OrderByDescending(s => s.EnrollmentDate);
             break;
          default:
             students = students.OrderBy(s => s.LastName);
             break;
       }
       return View(students.ToList());
    }
    

Этот код принимает параметр sortOrder из строки запроса в URL.This code receives a sortOrder parameter from the query string in the URL. Значение строки запроса предоставляется ASP.NET MVC в качестве параметра метода действия.The query string value is provided by ASP.NET MVC as a parameter to the action method. Параметр представляет собой строку, которая имеет значение "Name" или "Date", при необходимости за которой следует символ подчеркивания и строка "DESC" для указания порядка убывания.The parameter is a string that's either "Name" or "Date", optionally followed by an underscore and the string "desc" to specify descending order. По умолчанию задан порядок сортировки по возрастанию.The default sort order is ascending.

При первом запросе страницы Index строка запроса отсутствует.The first time the Index page is requested, there's no query string. Студенты отображаются в возрастающем порядке по LastName, который является значением по умолчанию, установленным в операторе switch.The students are displayed in ascending order by LastName, which is the default as established by the fall-through case in the switch statement. Когда пользователь щелкает гиперссылку заголовка столбца, в строку запроса подставляется соответствующее значение параметра sortOrder.When the user clicks a column heading hyperlink, the appropriate sortOrder value is provided in the query string.

Используются две переменные ViewBag, чтобы представление могли настроить гиперссылки заголовка столбца с соответствующими значениями строки запроса:The two ViewBag variables are used so that the view can configure the column heading hyperlinks with the appropriate query string values:

ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

Это тернарные условные операторы.These are ternary statements. Первый указывает, что если параметр sortOrder имеет значение null или пуст, ViewBag.NameSortParm должен иметь значение "Name_DESC"; в противном случае необходимо установить пустую строку.The first one specifies that if the sortOrder parameter is null or empty, ViewBag.NameSortParm should be set to "name_desc"; otherwise, it should be set to an empty string. Следующие два оператора устанавливают гиперссылки в заголовках столбцов в представлении следующим образом:These two statements enable the view to set the column heading hyperlinks as follows:

Текущий порядок сортировкиCurrent sort order Гиперссылка "Last Name" (Фамилия)Last Name Hyperlink Гиперссылка "Date" (Дата)Date Hyperlink
"Last Name" (Фамилия) по возрастаниюLast Name ascending descendingdescending ascendingascending
"Last Name" (Фамилия) по убываниюLast Name descending ascendingascending ascendingascending
"Date" (Дата) по возрастаниюDate ascending ascendingascending descendingdescending
"Date" (Дата) по убываниюDate descending ascendingascending ascendingascending

Метод использует LINQ to Entities , чтобы указать столбец для сортировки.The method uses LINQ to Entities to specify the column to sort by. Код создает переменную IQueryable<T> перед инструкцией switch, изменяет ее в операторе switch и вызывает метод ToList после инструкции switch.The code creates an IQueryable<T> variable before the switch statement, modifies it in the switch statement, and calls the ToList method after the switch statement. После создания и изменения переменных IQueryable запрос в базу данных не отправляется.When you create and modify IQueryable variables, no query is sent to the database. Запрос не выполняется до тех пор, пока не будет преобразован объект IQueryable в коллекцию путем вызова метода, такого как ToList.The query is not executed until you convert the IQueryable object into a collection by calling a method such as ToList. Таким образом, этот код приводит к выполнению одного запроса, который не выполняется до оператора return View.Therefore, this code results in a single query that is not executed until the return View statement.

В качестве альтернативы написанию различных операторов LINQ для каждого порядка сортировки можно динамически создать инструкцию LINQ.As an alternative to writing different LINQ statements for each sort order, you can dynamically create a LINQ statement. Дополнительные сведения о динамическом LINQ см. в разделе dynamic LINQ.For information about dynamic LINQ, see Dynamic LINQ.

  1. В виевс\студент\индекс.кштмлзамените элементы <tr> и <th> для строки заголовка выделенным кодом:In Views\Student\Index.cshtml, replace the <tr> and <th> elements for the heading row with the highlighted code:

    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    <table class="table">
        <tr>
            <th>
                @Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm })
            </th>
            <th>First Name
            </th>
            <th>
                @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm })
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
    

    Этот код использует сведения в свойствах ViewBag для настройки гиперссылок с соответствующими значениями строки запроса.This code uses the information in the ViewBag properties to set up hyperlinks with the appropriate query string values.

  2. Чтобы проверить, работает ли сортировка, запустите страницу и щелкните заголовки столбцов Last Name и Date регистрации .Run the page and click the Last Name and Enrollment Date column headings to verify that sorting works.

    После того как вы щелкните заголовок Last Name (фамилия ), учащиеся будут отображаться в порядке убывания фамилий.After you click the Last Name heading, students are displayed in descending last name order.

Чтобы добавить фильтрацию на страницу индекса учащихся, добавьте в представление текстовое поле и кнопку Submit и внесите соответствующие изменения в метод Index.To add filtering to the Students index page, you'll add a text box and a submit button to the view and make corresponding changes in the Index method. Текстовое поле позволяет ввести строку для поиска в полях Name и Last Name.The text box lets you enter a string to search for in the first name and last name fields.

Добавление функций фильтрации в метод IndexAdd filtering functionality to the Index method

  • В контроллерс\студентконтроллер.КСзамените метод Index следующим кодом (изменения выделены):In Controllers\StudentController.cs, replace the Index method with the following code (the changes are highlighted):

    public ViewResult Index(string sortOrder, string searchString)
    {
        ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
        ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
        var students = from s in db.Students
                       select s;
        if (!String.IsNullOrEmpty(searchString))
        {
            students = students.Where(s => s.LastName.Contains(searchString)
                                   || s.FirstMidName.Contains(searchString));
        }
        switch (sortOrder)
        {
            case "name_desc":
                students = students.OrderByDescending(s => s.LastName);
                break;
            case "Date":
                students = students.OrderBy(s => s.EnrollmentDate);
                break;
            case "date_desc":
                students = students.OrderByDescending(s => s.EnrollmentDate);
                break;
            default:
                students = students.OrderBy(s => s.LastName);
                break;
        }
    
        return View(students.ToList());
    }
    

Код добавляет параметр searchString в метод Index.The code adds a searchString parameter to the Index method. Значение строки поиска получается из текстового поля, которое мы добавили в представление Index.The search string value is received from a text box that you'll add to the Index view. Он также добавляет к инструкции LINQ предложение where, которое выбирает только учащихся, чье имя или фамилия содержат строку поиска.It also adds a where clause to the LINQ statement that selects only students whose first name or last name contains the search string. Инструкция, которая добавляет предложение Where, выполняется только в том случае, если имеется искомое значение.The statement that adds the Where clause executes only if there's a value to search for.

Note

Во многих случаях один и тот же метод можно вызвать либо в Entity Framework наборе сущностей, либо в виде метода расширения для коллекции в памяти.In many cases you can call the same method either on an Entity Framework entity set or as an extension method on an in-memory collection. Результаты обычно одинаковы, но в некоторых случаях они могут отличаться.The results are normally the same but in some cases may be different.

Например, .NET Framework реализация метода Contains возвращает все строки, когда в нее передается пустая строка, но поставщик Entity Framework для SQL Server Compact 4,0 возвращает нулевые строки для пустых строк.For example, the .NET Framework implementation of the Contains method returns all rows when you pass an empty string to it, but the Entity Framework provider for SQL Server Compact 4.0 returns zero rows for empty strings. Поэтому код в примере (поместив оператор Where в инструкцию if) гарантирует получение одинаковых результатов для всех версий SQL Server.Therefore the code in the example (putting the Where statement inside an if statement) makes sure that you get the same results for all versions of SQL Server. Кроме того, .NET Frameworkная реализация метода Contains выполняет сравнение с учетом регистра по умолчанию, но Entity Framework SQL Server поставщики выполняют сравнения без учета регистра по умолчанию.Also, the .NET Framework implementation of the Contains method performs a case-sensitive comparison by default, but Entity Framework SQL Server providers perform case-insensitive comparisons by default. Таким образом, вызов метода ToUpper для проверки явного нечувствительного к регистру регистра гарантирует, что результаты не изменяются при последующем изменении кода для использования репозитория, который вернет коллекцию IEnumerable вместо объекта IQueryable.Therefore, calling the ToUpper method to make the test explicitly case-insensitive ensures that results do not change when you change the code later to use a repository, which will return an IEnumerable collection instead of an IQueryable object. (При вызове метода Contains коллекции IEnumerable выполняется реализация .NET Framework; при вызове этого же метода у объекта IQueryable выполняется реализация поставщика базы данных.)(When you call the Contains method on an IEnumerable collection, you get the .NET Framework implementation; when you call it on an IQueryable object, you get the database provider implementation.)

Обработка значений NULL может также отличаться для разных поставщиков баз данных или при использовании объекта IQueryable по сравнению с IEnumerable коллекцией.Null handling may also be different for different database providers or when you use an IQueryable object compared to when you use an IEnumerable collection. Например, в некоторых сценариях Where условие, например table.Column != 0, может не возвращать столбцы, которые имеют null в качестве значения.For example, in some scenarios a Where condition such as table.Column != 0 may not return columns that have null as the value. По умолчанию EF создает дополнительные операторы SQL, чтобы обеспечить равенство значений NULL в базе данных, подобной работе в памяти, но можно установить флаг уседатабасенуллсемантикс в EF6 или вызвать метод усерелатионалнуллс в EF Core, чтобы настроить это поведение.By default, EF generates additional SQL operators to make equality between null values work in the database like it works in memory, but you can set the UseDatabaseNullSemantics flag in EF6 or call the UseRelationalNulls method in EF Core to configure this behavior.

Добавление поля поиска в представление индекса учащихсяAdd a search box to the Student index view

  1. В виевс\студент\индекс.кштмлДобавьте выделенный код непосредственно перед открывающим тегом table, чтобы создать заголовок, текстовое поле и кнопку поиска .In Views\Student\Index.cshtml, add the highlighted code immediately before the opening table tag in order to create a caption, a text box, and a Search button.

    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    
    @using (Html.BeginForm())
    {
        <p>
            Find by name: @Html.TextBox("SearchString")  
            <input type="submit" value="Search" /></p>
    }
    
    <table>
        <tr>
    
  2. Запустите страницу, введите строку поиска и нажмите кнопку Поиск , чтобы убедиться, что фильтрация работает.Run the page, enter a search string, and click Search to verify that filtering is working.

    Обратите внимание, что URL-адрес не содержит строку поиска "a". Это означает, что если вы заметите эту страницу в закладки, отфильтрованный список не будет получен при использовании закладки.Notice the URL doesn't contain the "an" search string, which means that if you bookmark this page, you won't get the filtered list when you use the bookmark. Это также относится к ссылкам сортировки столбцов, так как они будут сортировать весь список.This applies also to the column sort links, as they will sort the whole list. Вы измените кнопку поиска , чтобы в дальнейшем использовать строки запросов для критериев фильтрации.You'll change the Search button to use query strings for filter criteria later in the tutorial.

Добавление разбиения по страницамAdd paging

Чтобы добавить подкачку на страницу индекса учащихся, начните с установки пакета NuGet пажедлист. MVC .To add paging to the Students index page, you'll start by installing the PagedList.Mvc NuGet package. Затем вы вносите дополнительные изменения в метод Index и добавляете ссылки подкачки в представление Index.Then you'll make additional changes in the Index method and add paging links to the Index view. Пажедлист. MVC — это один из многих хороших пакетов разбиения по страницам и сортировки для ASP.NET MVC, и его использование здесь предназначено только в качестве примера, а не в качестве рекомендации по сравнению с другими вариантами.PagedList.Mvc is one of many good paging and sorting packages for ASP.NET MVC, and its use here is intended only as an example, not as a recommendation for it over other options.

Установка пакета NuGet Пажедлист. MVCInstall the PagedList.MVC NuGet package

Пакет NuGet пажедлист. MVC автоматически устанавливает пакет пажедлист в качестве зависимости.The NuGet PagedList.Mvc package automatically installs the PagedList package as a dependency. Пакет пажедлист устанавливает тип коллекции PagedList и методы расширения для коллекций IQueryable и IEnumerable.The PagedList package installs a PagedList collection type and extension methods for IQueryable and IEnumerable collections. Методы расширения создают одну страницу данных в коллекции PagedList из IQueryable или IEnumerable, а коллекция PagedList предоставляет несколько свойств и методов, которые упрощают разбиение на страницы.The extension methods create a single page of data in a PagedList collection out of your IQueryable or IEnumerable, and the PagedList collection provides several properties and methods that facilitate paging. Пакет пажедлист. MVC устанавливает вспомогательный метод разбиения на страницы, который отображает кнопки разбиения на страницы.The PagedList.Mvc package installs a paging helper that displays the paging buttons.

  1. В меню Сервис выберите Диспетчер пакетов NuGet , а затем — консоль диспетчера пакетов.From the Tools menu, select NuGet Package Manager and then Package Manager Console.

  2. В окне консоли диспетчера пакетов убедитесь, что источник пакета имеет значение NuGet.org , а проект по умолчаниюContosoUniversity, а затем введите следующую команду:In the Package Manager Console window, make sure the Package source is nuget.org and the Default project is ContosoUniversity, and then enter the following command:

    Install-Package PagedList.Mvc
    
  3. Создайте проект.Build the project.

Добавление разбиения на страницы в метод IndexAdd paging functionality to the Index method

  1. В контроллерс\студентконтроллер.КСдобавьте оператор using для пространства имен PagedList.In Controllers\StudentController.cs, add a using statement for the PagedList namespace:

    using PagedList;
    
  2. Замените метод Index следующим кодом:Replace the Index method with the following code:

    public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
    {
       ViewBag.CurrentSort = sortOrder;
       ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
       ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
    
       if (searchString != null)
       {
          page = 1;
       }
       else
       {
          searchString = currentFilter;
       }
    
       ViewBag.CurrentFilter = searchString;
    
       var students = from s in db.Students
                      select s;
       if (!String.IsNullOrEmpty(searchString))
       {
          students = students.Where(s => s.LastName.Contains(searchString)
                                 || s.FirstMidName.Contains(searchString));
       }
       switch (sortOrder)
       {
          case "name_desc":
             students = students.OrderByDescending(s => s.LastName);
             break;
          case "Date":
             students = students.OrderBy(s => s.EnrollmentDate);
             break;
          case "date_desc":
             students = students.OrderByDescending(s => s.EnrollmentDate);
             break;
          default:  // Name ascending 
             students = students.OrderBy(s => s.LastName);
             break;
       }
    
       int pageSize = 3;
       int pageNumber = (page ?? 1);
       return View(students.ToPagedList(pageNumber, pageSize));
    }
    

    Этот код добавляет параметр page, текущий параметр порядка сортировки и текущий параметр фильтра в сигнатуру метода:This code adds a page parameter, a current sort order parameter, and a current filter parameter to the method signature:

    public ActionResult Index(string sortOrder, string currentFilter, string searchString, int? page)
    

    При первом отображении страницы или если пользователь не щелкнул ссылку на подкачку или сортировку, все параметры имеют значение null.The first time the page is displayed, or if the user hasn't clicked a paging or sorting link, all the parameters are null. При нажатии ссылки на подкачку переменная page содержит номер отображаемой страницы.If a paging link is clicked, the page variable contains the page number to display.

    Свойство ViewBag предоставляет представление с текущим порядком сортировки, поскольку оно должно быть включено в ссылки разбиения на страницы, чтобы порядок сортировки совпадал с порядком разбиения на страницы:A ViewBag property provides the view with the current sort order, because this must be included in the paging links in order to keep the sort order the same while paging:

    ViewBag.CurrentSort = sortOrder;
    

    Другое свойство, ViewBag.CurrentFilter, предоставляет представление с текущей строкой фильтра.Another property, ViewBag.CurrentFilter, provides the view with the current filter string. Это значение необходимо включить в ссылки для перелистывания, чтобы при смене страницы сохранить настройки фильтра, кроме того, необходимо восстановить значение фильтра в текстовом поле после обновления страницы.This value must be included in the paging links in order to maintain the filter settings during paging, and it must be restored to the text box when the page is redisplayed. Если строка поиска изменяется во время перелистывания, то номер страницы должен быть сброшен на 1, так как с новым фильтром изменится состав отображаемых данных.If the search string is changed during paging, the page has to be reset to 1, because the new filter can result in different data to display. Строка поиска изменяется при вводе значения в текстовое поле и нажатии кнопки Submit (отправить).The search string is changed when a value is entered in the text box and the submit button is pressed. В этом случае параметр searchString не равен null.In that case, the searchString parameter is not null.

    if (searchString != null)
    {
        page = 1;
    }
    else
    {
        searchString = currentFilter;
    }
    

    В конце метода метод расширения ToPagedList объекта Students IQueryable преобразует запрос учащегося на одну страницу учащихся в типе коллекции, который поддерживает разбиение на страницы.At the end of the method, the ToPagedList extension method on the students IQueryable object converts the student query to a single page of students in a collection type that supports paging. После этого одна страница учащихся передается в представление:That single page of students is then passed to the view:

    int pageSize = 3;
    int pageNumber = (page ?? 1);
    return View(students.ToPagedList(pageNumber, pageSize));
    

    Метод ToPagedList принимает номер страницы.The ToPagedList method takes a page number. Два знака вопроса представляют оператор объединения со значением NULL.The two question marks represent the null-coalescing operator. Этот оператор определяет значение по умолчанию для значения null; выражение (page ?? 1) возвращает значение переменной page, если она имеет значение, и возвращает 1, если переменная page имеет значение null.The null-coalescing operator defines a default value for a nullable type; the expression (page ?? 1) means return the value of page if it has a value, or return 1 if page is null.

  1. В виевс\студент\индекс.кштмлзамените существующий код следующим кодом.In Views\Student\Index.cshtml, replace the existing code with the following code. Изменения выделены.The changes are highlighted.

    @model PagedList.IPagedList<ContosoUniversity.Models.Student>
    @using PagedList.Mvc;
    <link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
    
    @{
        ViewBag.Title = "Students";
    }
    
    <h2>Students</h2>
    
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    @using (Html.BeginForm("Index", "Student", FormMethod.Get))
    {
        <p>
            Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
            <input type="submit" value="Search" />
        </p>
    }
    <table class="table">
        <tr>
            <th>
                @Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th>
                First Name
            </th>
            <th>
                @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm, currentFilter=ViewBag.CurrentFilter })
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstMidName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
                @Html.ActionLink("Details", "Details", new { id=item.ID }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.ID })
            </td>
        </tr>
    }
    
    </table>
    <br />
    Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount
    
    @Html.PagedListPager(Model, page => Url.Action("Index", 
        new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
    

    Оператор @model в начале страницы указывает на то, что теперь представление принимает объект PagedList, а не объект List.The @model statement at the top of the page specifies that the view now gets a PagedList object instead of a List object.

    Инструкция using для PagedList.Mvc предоставляет доступ к вспомогательному модулю MVC для кнопок разбиения на страницы.The using statement for PagedList.Mvc gives access to the MVC helper for the paging buttons.

    Код использует перегрузку бегинформ , которая позволяет ему указать форммесод. Get.The code uses an overload of BeginForm that allows it to specify FormMethod.Get.

    @using (Html.BeginForm("Index", "Student", FormMethod.Get))
    {
        <p>
            Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)  
            <input type="submit" value="Search" />
        </p>
    }
    

    Бегинформ по умолчанию отправляет данные формы с помощью записи, что означает, что параметры передаются в тексте сообщения HTTP, а не в URL-адресе в виде строк запроса.The default BeginForm submits form data with a POST, which means that parameters are passed in the HTTP message body and not in the URL as query strings. При указании метода HTTP GET данные формы передаются в URL-адресе в виде строк запроса, что позволяет добавлять URL-адреса в закладки.When you specify HTTP GET, the form data is passed in the URL as query strings, which enables users to bookmark the URL. Рекомендации консорциума W3C по использованию протокола HTTP Get рекомендуют использовать инструкцию Get, если действие не приводит к обновлению.The W3C guidelines for the use of HTTP GET recommend that you should use GET when the action does not result in an update.

    Текстовое поле инициализируется текущей строкой поиска, поэтому при щелчке на новой странице можно увидеть текущую строку поиска.The text box is initialized with the current search string so when you click a new page you can see the current search string.

    Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
    

    Ссылки в заголовках столбцов передают в контроллер при помощи строки запроса текущее значение строки поиска, чтобы пользователь мог сортировать отфильтрованные данные:The column header links use the query string to pass the current search string to the controller so that the user can sort within filter results:

    @Html.ActionLink("Last Name", "Index", new { sortOrder=ViewBag.NameSortParm, currentFilter=ViewBag.CurrentFilter })
    

    Отобразится текущая страница и общее количество страниц.The current page and total number of pages are displayed.

    Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount
    

    Если нет страниц для отображения, отображается страница 0 из 0.If there are no pages to display, "Page 0 of 0" is shown. (В этом случае номер страницы больше, чем число страниц, поскольку Model.PageNumber равно 1, а Model.PageCount — 0.)(In that case the page number is greater than the page count because Model.PageNumber is 1, and Model.PageCount is 0.)

    Кнопки разбиения на страницы отображаются PagedListPager вспомогательным модулем:The paging buttons are displayed by the PagedListPager helper:

    @Html.PagedListPager( Model, page => Url.Action("Index", new { page }) )
    

    Модуль поддержки PagedListPager предоставляет ряд параметров, которые можно настраивать, включая URL-адреса и стили.The PagedListPager helper provides a number of options that you can customize, including URLs and styling. Дополнительные сведения см. в разделе тройгуде/пажедлист на сайте GitHub.For more information, see TroyGoode / PagedList on the GitHub site.

  2. Запустите страницу.Run the page.

    Чтобы убедиться, что постраничный просмотр работает, нажимайте кнопки перелистывания при различном порядке сортировки.Click the paging links in different sort orders to make sure paging works. Затем введите строку поиска и повторите перелистывание, чтобы убедиться, что разбиение на страницы работает корректно вместе с сортировкой и фильтрацией.Then enter a search string and try paging again to verify that paging also works correctly with sorting and filtering.

Создание страницы сведенийCreate an About page

На странице со сведениями о веб-сайте университета Contoso вы увидите, сколько учащихся зарегистрировано для каждой даты регистрации.For the Contoso University website's About page, you'll display how many students have enrolled for each enrollment date. Для этого понадобится группировка и выполнение простых расчетов в группах.This requires grouping and simple calculations on the groups. Для выполнения этой задачи нам потребуется следующее:To accomplish this, you'll do the following:

  • Создать класс модели представления для данных, которые необходимо передать в представление.Create a view model class for the data that you need to pass to the view.
  • Измените метод About в контроллере Home.Modify the About method in the Home controller.
  • Измените представление About.Modify the About view.

Создание модели представленияCreate the View Model

Создайте папку ViewModels в папке проекта.Create a ViewModels folder in the project folder. В этой папке добавьте файл класса EnrollmentDateGroup.CS и замените код шаблона следующим кодом:In that folder, add a class file EnrollmentDateGroup.cs and replace the template code with the following code:

using System;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.ViewModels
{
    public class EnrollmentDateGroup
    {
        [DataType(DataType.Date)]
        public DateTime? EnrollmentDate { get; set; }

        public int StudentCount { get; set; }
    }
}

Изменение контроллера HomeModify the Home Controller

  1. В HomeController.CSдобавьте в начало файла следующие инструкции using:In HomeController.cs, add the following using statements at the top of the file:

    using ContosoUniversity.DAL;
    using ContosoUniversity.ViewModels;
    
  2. Добавьте переменную класса для контекста базы данных сразу после открывающей фигурной скобки для класса:Add a class variable for the database context immediately after the opening curly brace for the class:

    public class HomeController : Controller
    {
        private SchoolContext db = new SchoolContext();
    
  3. Замените метод About следующим кодом:Replace the About method with the following code:

    public ActionResult About()
    {
        IQueryable<EnrollmentDateGroup> data = from student in db.Students
                   group student by student.EnrollmentDate into dateGroup
                   select new EnrollmentDateGroup()
                   {
                       EnrollmentDate = dateGroup.Key,
                       StudentCount = dateGroup.Count()
                   };
        return View(data.ToList());
    }
    

    Запрос LINQ группирует записи из таблицы студентов по дате зачисления, вычисляет число записей в каждой группе и сохраняет результаты в коллекцию объектов моделей представления EnrollmentDateGroup.The LINQ statement groups the student entities by enrollment date, calculates the number of entities in each group, and stores the results in a collection of EnrollmentDateGroup view model objects.

  4. Добавьте метод Dispose:Add a Dispose method:

    protected override void Dispose(bool disposing)
    {
        db.Dispose();
        base.Dispose(disposing);
    }
    

Изменение представления AboutModify the About View

  1. Замените код в файле виевс\хоме\абаут.кштмл следующим кодом:Replace the code in the Views\Home\About.cshtml file with the following code:

    @model IEnumerable<ContosoUniversity.ViewModels.EnrollmentDateGroup>
               
    @{
        ViewBag.Title = "Student Body Statistics";
    }
    
    <h2>Student Body Statistics</h2>
    
    <table>
        <tr>
            <th>
                Enrollment Date
            </th>
            <th>
                Students
            </th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                @item.StudentCount
            </td>
        </tr>
    }
    </table>
    
  2. Запустите приложение и щелкните ссылку About (о программе ).Run the app and click the About link.

    Число учащихся для каждой даты регистрации отображается в таблице.The count of students for each enrollment date displays in a table.

    About_page

Получение кодаGet the code

Скачать завершенный проектDownload the Completed Project

Дополнительные ресурсыAdditional resources

Ссылки на другие ресурсы Entity Framework можно найти в материалах, рекомендуемых для доступа к данным ASP.NET.Links to other Entity Framework resources can be found in ASP.NET Data Access - Recommended Resources.

Дальнейшие действияNext steps

Изучив это руководство, вы:In this tutorial, you:

  • Добавление ссылок для сортировки столбцовAdd column sort links
  • Добавление поля поискаAdd a Search box
  • Добавление разбиения по страницамAdd paging
  • Создание страницы сведенийCreate an About page

Перейдите к следующей статье, чтобы узнать, как использовать устойчивость подключений и перехват команд.Advance to the next article to learn how to use connection resiliency and command interception.