Упорядочение нестандартно разбитых по страницам данных (C#)Sorting Custom Paged Data (C#)

по Скотт Митчеллby Scott Mitchell

Скачивание примера приложения или Загрузка PDF-файлаDownload Sample App or Download PDF

В предыдущем учебном курсе мы узнали, как реализовать пользовательское разбиение по страницам при представлении данных на веб-странице.In the previous tutorial we learned how to implement custom paging when presenting data on a web page. В этом учебнике мы видим, как расширить предыдущий пример, включив поддержку сортировки пользовательского разбиения по страницам.In this tutorial we see how to extend the preceding example to include support for sorting custom paging.

ВведениеIntroduction

По сравнению с разбиением по страницам по умолчанию, пользовательское разбиение по страницам может повысить производительность разбиения данных по нескольким порядковым показателям, делая пользовательский разбиение по страницам де-факто при разбиении больших объемов данных.Compared to default paging, custom paging can improve the performance of paging through data by several orders of magnitude, making custom paging the de facto paging implementation choice when paging through large amounts of data. Реализация пользовательского разбиения по страницам является более сложной, чем реализация разбиения по страницам по умолчанию, особенно при добавлении сортировки к набору.Implementing custom paging is more involved than implementing default paging, however, especially when adding sorting to the mix. В этом учебнике мы добавим пример из предыдущего, чтобы включить поддержку сортировки и пользовательского разбиения на страницы.In this tutorial we'll extend the example from the preceding one to include support for sorting and custom paging.

Note

Поскольку этот учебник построен на предыдущем этапе, прежде чем начать создание декларативного синтаксиса в элементе <asp:Content> из предыдущей веб-страницы Tutorial (EfficientPaging.aspx) и вставить его между элементом <asp:Content> на странице SortParameter.aspx.Since this tutorial builds upon the preceding one, before beginning take a moment to copy the declarative syntax within the <asp:Content> element from the preceding tutorial s web page (EfficientPaging.aspx) and paste it between the <asp:Content> element in the SortParameter.aspx page. Дополнительные сведения о репликации функций одной ASP.NET страницы на другую см. в статье Добавление элементов управления проверки в учебник по интерфейсам правки и вставки .Refer back to Step 1 of the Adding Validation Controls to the Editing and Inserting Interfaces tutorial for a more detailed discussion on replicating the functionality of one ASP.NET page to another.

Шаг 1. Проверка пользовательского метода разбиения на страницыStep 1: Reexamining the Custom Paging Technique

Для правильной работы пользовательского разбиения по страницам необходимо реализовать некоторый метод, который может эффективно извлечь определенное подмножество записей, учитывая параметры "Индекс начальной строки" и "максимальное число строк".For custom paging to work properly, we must implement some technique that can efficiently grab a particular subset of records given the Start Row Index and Maximum Rows parameters. Для достижения этой цели можно использовать несколько методов.There are a handful of techniques that can be used to achieve this aim. В предыдущем учебном курсе мы рассматривали эту задачу с помощью Microsoft SQL Server 2005 s New ROW_NUMBER() ранжирующие функция.In the preceding tutorial we looked at accomplishing this using Microsoft SQL Server 2005 s new ROW_NUMBER() ranking function. Вкратце, функция ранжирования ROW_NUMBER() назначает номер строки каждой строке, возвращаемой запросом, который ранжирован по указанному порядку сортировки.In short, the ROW_NUMBER() ranking function assigns a row number to each row returned by a query that is ranked by a specified sort order. Затем нужно получить соответствующее подмножество записей, возвращая определенный раздел нумерованных результатов.The appropriate subset of records is then obtained by returning a particular section of the numbered results. В следующем запросе показано, как использовать этот метод для возврата продуктов с номерами от 11 до 20 при ранжировании результатов, упорядоченных в алфавитном порядке по ProductName:The following query illustrates how to use this technique to return those products numbered 11 through 20 when ranking the results ordered alphabetically by the ProductName:

SELECT ProductID, ProductName, ...
FROM
   (SELECT ProductID, ProductName, ..., ROW_NUMBER() OVER
        (ORDER BY ProductName) AS RowRank
    FROM Products) AS ProductsWithRowNumbers
WHERE RowRank > 10 AND RowRank <= 20

Этот метод хорошо подходит для разбиения на страницы с использованием определенного порядка сортировки (в данном случаеProductName сортируются в алфавитном порядке), но запрос необходимо изменить, чтобы отобразить результаты, отсортированные по другому выражению сортировки.This technique works well for paging using a specific sort order (ProductName sorted alphabetically, in this case), but the query needs to be modified to show the results sorted by a different sort expression. В идеале приведенный выше запрос может быть переписан для использования параметра в предложении OVER следующим образом:Ideally, the above query could be rewritten to use a parameter in the OVER clause, like so:

SELECT ProductID, ProductName, ...
FROM
   (SELECT ProductID, ProductName, ..., ROW_NUMBER() OVER
        (ORDER BY @sortExpression) AS RowRank
    FROM Products) AS ProductsWithRowNumbers
WHERE RowRank > 10 AND RowRank <= 20

К сожалению, параметризованные ORDER BY предложения не допускаются.Unfortunately, parameterized ORDER BY clauses are not allowed. Вместо этого необходимо создать хранимую процедуру, которая принимает входной параметр @sortExpression, но использует одно из следующих решений.Instead, we must create a stored procedure that accepts a @sortExpression input parameter, but uses one of the following workarounds:

  • Напишите жестко запрограммированные запросы для каждого выражения сортировки, которое может использоваться; затем используйте IF/ELSE инструкции T-SQL, чтобы определить, какой запрос следует выполнить.Write hard-coded queries for each of the sort expressions that may be used; then, use IF/ELSE T-SQL statements to determine which query to execute.
  • Используйте оператор CASE для предоставления динамических ORDER BY выражений на основе входного параметра @sortExpressio n; Дополнительные сведения см. в разделе Использование для динамической сортировки результатов запроса статьи инструкции SQL CASE .Use a CASE statement to provide dynamic ORDER BY expressions based on the @sortExpressio n input parameter; see the Used to Dynamically Sort Query Results section in The Power of SQL CASE Statements for more information.
  • Создание соответствующего запроса в виде строки в хранимой процедуре, а затем использование sp_executesql системной хранимой процедуры для выполнения динамического запроса.Craft the appropriate query as a string in the stored procedure and then use the sp_executesql system stored procedure to execute the dynamic query.

Каждое из этих решений имеет определенные недостатки.Each of these workarounds has some drawbacks. Первый вариант не так, как и другие два, так как он требует создания запроса для каждого возможного выражения сортировки.The first option is not as maintainable as the other two as it requires that you create a query for each possible sort expression. Таким образом, если позже вы решили добавить в GridView новые поля с возможностью сортировки, потребуется вернуться и обновить хранимую процедуру.Therefore, if later you decide to add new, sortable fields to the GridView you will also need to go back and update the stored procedure. Второй подход имеет некоторые тонкости, которые приводят к снижению производительности при сортировке по столбцам нестроковой базы данных, и при этом возникают те же проблемы, что и в первом случае.The second approach has some subtleties that introduce performance concerns when sorting by non-string database columns and also suffers from the same maintainability issues as the first. Третий вариант, в котором используется динамический SQL, представляет риск для атаки путем внедрения кода SQL, если злоумышленник может выполнить хранимую процедуру, передав значения входных параметров по своему выбору.And the third choice, which uses dynamic SQL, introduces the risk for a SQL injection attack if an attacker is able to execute the stored procedure passing in the input parameter values of their choosing.

Хотя ни один из этих подходов не является идеальным, я думаю, что третий вариант является лучшим из трех.While none of these approaches is perfect, I think the third option is the best of the three. Благодаря использованию динамического SQL он предлагает уровень гибкости, отличный от двух других.With its use of dynamic SQL, it offers a level of flexibility the other two do not. Более того, атака путем внедрения кода SQL может быть использована только в том случае, если злоумышленник сможет выполнить хранимую процедуру, передав входные параметры по своему усмотрению.Furthermore, a SQL injection attack can only be exploited if an attacker is able to execute the stored procedure passing in the input parameters of his choice. Поскольку DAL использует параметризованные запросы, ADO.NET будет защищать эти параметры, которые отправляются в базу данных через архитектуру, что означает, что уязвимость атаки путем внедрения кода SQL существует только в том случае, если злоумышленник может напрямую выполнить хранимую процедуру.Since the DAL uses parameterized queries, ADO.NET will protect those parameters that are sent to the database through the architecture, meaning that the SQL injection attack vulnerability only exists if the attacker can directly execute the stored procedure.

Чтобы реализовать эту функцию, создайте новую хранимую процедуру в базе данных Northwind с именем GetProductsPagedAndSorted.To implement this functionality, create a new stored procedure in the Northwind database named GetProductsPagedAndSorted. Эта хранимая процедура должна принимать три входных параметра: @sortExpression, входной параметр типа nvarchar(100), который указывает, как результаты должны быть отсортированы и добавлены непосредственно после текста ORDER BY в предложении OVER. и @startRowIndex и @maximumRowsте же два целочисленных входных параметра из GetProductsPaged хранимой процедуры, проверенных в предыдущем руководстве.This stored procedure should accept three input parameters: @sortExpression, an input parameter of type nvarchar(100) that specifies how the results should be sorted and is injected directly after the ORDER BY text in the OVER clause; and @startRowIndex and @maximumRows, the same two integer input parameters from the GetProductsPaged stored procedure examined in the preceding tutorial. Создайте GetProductsPagedAndSorted хранимую процедуру, используя следующий скрипт:Create the GetProductsPagedAndSorted stored procedure using the following script:

CREATE PROCEDURE dbo.GetProductsPagedAndSorted
(
    @sortExpression nvarchar(100),
    @startRowIndex int,
    @maximumRows int
)
AS
-- Make sure a @sortExpression is specified
IF LEN(@sortExpression) = 0
    SET @sortExpression = 'ProductID'
-- Issue query
DECLARE @sql nvarchar(4000)
SET @sql = 'SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
            UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued,
            CategoryName, SupplierName
            FROM (SELECT ProductID, ProductName, p.SupplierID, p.CategoryID,
                    QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
                    ReorderLevel, Discontinued,
                  c.CategoryName, s.CompanyName AS SupplierName,
                   ROW_NUMBER() OVER (ORDER BY ' + @sortExpression + ') AS RowRank
            FROM Products AS p
                    INNER JOIN Categories AS c ON
                        c.CategoryID = p.CategoryID
                    INNER JOIN Suppliers AS s ON
                        s.SupplierID = p.SupplierID) AS ProductsWithRowNumbers
            WHERE     RowRank > ' + CONVERT(nvarchar(10), @startRowIndex) +
                ' AND RowRank <= (' + CONVERT(nvarchar(10), @startRowIndex) + ' + '
                + CONVERT(nvarchar(10), @maximumRows) + ')'
-- Execute the SQL query
EXEC sp_executesql @sql

Хранимая процедура начинается с того, что указано значение параметра @sortExpression.The stored procedure starts by ensuring that a value for the @sortExpression parameter has been specified. Если он отсутствует, результаты ранжированы по ProductID.If it is missing, the results are ranked by ProductID. Далее создается динамический запрос SQL.Next, the dynamic SQL query is constructed. Обратите внимание, что динамический запрос SQL немного отличается от предыдущих запросов, использовавшихся для получения всех строк из таблицы Products.Note that the dynamic SQL query here differs slightly from our previous queries used to retrieve all rows from the Products table. В предыдущих примерах мы получили для каждого продукта связанные категории и имена поставщиков с помощью вложенного запроса.In prior examples, we obtained each product s associated category s and supplier s names using a subquery. Это решение было принято в учебнике Создание уровня доступа к данным и было сделано вместо использования JOIN s, так как TableAdapter не может автоматически создавать связанные методы вставки, обновления и удаления для таких запросов.This decision was made back in the Creating a Data Access Layer tutorial and was done in lieu of using JOIN s because the TableAdapter cannot automatically create the associated insert, update, and delete methods for such queries. Однако GetProductsPagedAndSorted хранимая процедура должна использовать JOIN s, чтобы результаты упорядочивались по именам категорий или поставщиков.The GetProductsPagedAndSorted stored procedure, however, must use JOIN s for the results to be ordered by the category or supplier names.

Этот динамический запрос строится путем сцепления статических частей запроса и параметров @sortExpression, @startRowIndexи @maximumRows.This dynamic query is built up by concatenating the static query portions and the @sortExpression, @startRowIndex, and @maximumRows parameters. Поскольку @startRowIndex и @maximumRows являются целочисленными параметрами, они должны быть преобразованы в nvarchar для правильного сцепления.Since @startRowIndex and @maximumRows are integer parameters, they must be converted into nvarchars in order to be correctly concatenated. После создания динамического SQL-запроса он выполняется с помощью sp_executesql.Once this dynamic SQL query has been constructed, it is executed via sp_executesql.

Уделите несколько минут тестированию этой хранимой процедуры с различными значениями параметров @sortExpression, @startRowIndexи @maximumRows.Take a moment to test this stored procedure with different values for the @sortExpression, @startRowIndex, and @maximumRows parameters. В обозреватель сервера щелкните правой кнопкой мыши имя хранимой процедуры и выберите команду выполнить.From the Server Explorer, right-click on the stored procedure name and choose Execute. Откроется диалоговое окно Запуск хранимой процедуры, в котором можно ввести входные параметры (см. рис. 1).This will bring up the Run Stored Procedure dialog box into which you can enter the input parameters (see Figure 1). Чтобы отсортировать результаты по имени категории, используйте категорию CategoryName для значения параметра @sortExpression. для сортировки по названию компании поставщика используйте CompanyName.To sort the results by the category name, use CategoryName for the @sortExpression parameter value; to sort by the supplier s company name, use CompanyName. Указав значения параметров, нажмите кнопку ОК.After providing the parameters values, click OK. Результаты отображаются в окне Вывод.The results are displayed in the Output window. На рис. 2 показаны результаты при возврате продуктов с рангами от 11 до 20 при упорядочении по UnitPrice в порядке убывания.Figure 2 shows the results when returning products ranked 11 through 20 when ordering by the UnitPrice in descending order.

Попробуйте использовать другие значения для хранимой процедуры с тремя входными параметрами

Рис. 1. Попробуйте использовать другие значения для хранимой процедуры с тремя входными параметрамиFigure 1: Try Different Values for the Stored Procedure s Three Input Parameters

результаты хранимых процедур отображаются в окно выводаThe Stored Procedure s Results are Shown in the Output Window

Рис. 2. Результаты хранимых процедур отображаются в окно вывода (щелкните, чтобы просмотреть изображение с полным размером)Figure 2: The Stored Procedure s Results are Shown in the Output Window (Click to view full-size image)

Note

При ранжировании результатов по указанному столбцу ORDER BY в предложении OVER SQL Server необходимо отсортировать результаты.When ranking the results by the specified ORDER BY column in the OVER clause, SQL Server must sort the results. Это быстрая операция, если имеется кластеризованный индекс по столбцам, в котором упорядочиваются результаты, или если имеется индекс покрытия, но в противном случае он может оказаться более дорогостоящим.This is a quick operation if there is a clustered index over the column(s) the results are being ordered by or if there is a covering index, but can be more costly otherwise. Чтобы повысить производительность для достаточно больших запросов, рассмотрите возможность добавления некластеризованного индекса для столбца, по которому упорядочиваются результаты.To improve performance for sufficiently large queries, consider adding a non-clustered index for the column by which the results are ordered by. Дополнительные сведения см. в разделе ранжирующие функции и производительность в SQL Server 2005 .Refer to Ranking Functions and Performance in SQL Server 2005 for more details.

Шаг 2. дополнение уровней доступа к данным и бизнес-логикиStep 2: Augmenting the Data Access and Business Logic Layers

После создания GetProductsPagedAndSorted хранимой процедуры наш следующий шаг заключается в предоставлении средств для выполнения этой хранимой процедуры через нашу архитектуру приложения.With the GetProductsPagedAndSorted stored procedure created, our next step is to provide a means to execute that stored procedure through our application architecture. Это влечет за собой добавление соответствующего метода в DAL и BLL.This entails adding an appropriate method to both the DAL and BLL. Начнем с добавления метода в DAL.Let s start by adding a method to the DAL. Откройте Northwind.xsd типизированный набор данных, щелкните правой кнопкой мыши ProductsTableAdapterи выберите пункт Добавить запрос в контекстном меню.Open the Northwind.xsd Typed DataSet, right-click on the ProductsTableAdapter, and choose the Add Query option from the context menu. Как мы делали в предыдущем учебном курсе, мы хотим настроить этот новый метод DAL для использования существующей хранимой процедуры, GetProductsPagedAndSortedв данном случае.As we did in the preceding tutorial, we want to configure this new DAL method to use an existing stored procedure - GetProductsPagedAndSorted, in this case. Начните с указания того, что новый метод TableAdapter должен использовать существующую хранимую процедуру.Start by indicating that you want the new TableAdapter method to use an existing stored procedure.

Выберите использование существующей хранимой процедуры

Рис. 3. Выбор использования существующей хранимой процедурыFigure 3: Choose to Use an Existing Stored Procedure

Чтобы указать используемую хранимую процедуру, выберите GetProductsPagedAndSorted хранимая процедура из раскрывающегося списка на следующем экране.To specify the stored procedure to use, select the GetProductsPagedAndSorted stored procedure from the drop-down list in the next screen.

Использование хранимой процедуры Жетпродуктспажедандсортед

Рис. 4. использование хранимой процедуры жетпродуктспажедандсортедFigure 4: Use the GetProductsPagedAndSorted Stored Procedure

Эта хранимая процедура возвращает набор записей в виде результатов, поэтому на следующем экране указывается, что он возвращает табличные данные.This stored procedure returns a set of records as its results so, in the next screen, indicate that it returns tabular data.

Указывает, что хранимая процедура возвращает табличные данные

Рис. 5. Указание того, что хранимая процедура возвращает табличные данныеFigure 5: Indicate that the Stored Procedure Returns Tabular Data

Наконец, создайте методы DAL, которые используют и заполнение таблицы DataTable, и возвращают шаблоны DataTable, имена методов FillPagedAndSorted и GetProductsPagedAndSortedсоответственно.Finally, create DAL methods that use both the Fill a DataTable and Return a DataTable patterns, naming the methods FillPagedAndSorted and GetProductsPagedAndSorted, respectively.

Выбор имен методов

Рис. 6. Выбор имен методовFigure 6: Choose the Methods Names

Теперь, когда мы расширили DAL, мы повторно готовы к переходу на слой BLL.Now that we ve extended the DAL, we re ready to turn to the BLL. Откройте файл ProductsBLL класса и добавьте новый метод GetProductsPagedAndSorted.Open the ProductsBLL class file and add a new method, GetProductsPagedAndSorted. Этот метод должен принимать три входных параметра sortExpression, startRowIndexи maximumRows и следует просто вызвать метод DAL s GetProductsPagedAndSorted следующим образом:This method needs to accept three input parameters sortExpression, startRowIndex, and maximumRows and should simply call down into the DAL s GetProductsPagedAndSorted method, like so:

[System.ComponentModel.DataObjectMethodAttribute(
    System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.ProductsDataTable GetProductsPagedAndSorted(
    string sortExpression, int startRowIndex, int maximumRows)
{
    return Adapter.GetProductsPagedAndSorted
        (sortExpression, startRowIndex, maximumRows);
}

Шаг 3. Настройка элемента ObjectDataSource для передачи в параметр SortExpressionStep 3: Configuring the ObjectDataSource to Pass in the SortExpression Parameter

Добавив DAL и BLL для включения методов, использующих хранимую процедуру GetProductsPagedAndSorted, остается только настроить ObjectDataSource на странице SortParameter.aspx, чтобы использовать новый метод BLL и передать параметр SortExpression на основе столбца, который пользователь запросил для сортировки результатов.Having augmented the DAL and BLL to include methods that utilize the GetProductsPagedAndSorted stored procedure, all that remains is to configure the ObjectDataSource in the SortParameter.aspx page to use the new BLL method and to pass in the SortExpression parameter based on the column that the user has requested to sort the results by.

Начните с изменения SelectMethod ObjectDataSource s с GetProductsPaged на GetProductsPagedAndSorted.Start by changing the ObjectDataSource s SelectMethod from GetProductsPaged to GetProductsPagedAndSorted. Это можно сделать с помощью мастера настройки источника данных, из окно свойств или непосредственно с помощью декларативного синтаксиса.This can be done through the Configure Data Source wizard, from the Properties window, or directly through the declarative syntax. Далее необходимо предоставить значение для Свойства ObjectDataSourceSortParameterName.Next, we need to provide a value for the ObjectDataSource s SortParameterName property. Если это свойство задано, ObjectDataSource пытается передать в SelectMethodсвойство SortExpression GridView s.If this property is set, the ObjectDataSource attempts to pass in the GridView s SortExpression property to the SelectMethod. В частности, ObjectDataSource ищет входной параметр, имя которого равно значению свойства SortParameterName.In particular, the ObjectDataSource looks for an input parameter whose name is equal to the value of the SortParameterName property. Так как метод BLL GetProductsPagedAndSorted имеет входной параметр Expression сортировки с именем sortExpression, задайте для свойства ObjectDataSource SortExpression значение sortExpression.Since the BLL s GetProductsPagedAndSorted method has the sort expression input parameter named sortExpression, set the ObjectDataSource s SortExpression property to sortExpression .

После внесения этих двух изменений декларативный синтаксис ObjectDataSource s должен выглядеть следующим образом:After making these two changes, the ObjectDataSource s declarative syntax should look similar to the following:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
    SelectMethod="GetProductsPagedAndSorted" EnablePaging="True"
    SelectCountMethod="TotalNumberOfProducts" SortParameterName="sortExpression">
</asp:ObjectDataSource>

Note

Как и в предыдущем руководстве, убедитесь, что ObjectDataSource не включает входные параметры SortExpression, StartRowIndex или maximumRows в коллекцию SelectParameters.As with the preceding tutorial, ensure that the ObjectDataSource does not include the sortExpression, startRowIndex, or maximumRows input parameters in its SelectParameters collection.

Чтобы включить сортировку в GridView, просто установите флажок Enable Sort (включить сортировку) в смарт-теге GridView s, который задает для свойства AllowSorting GridView s значение true и вызывает визуализацию текста заголовка для каждого столбца в виде элемента управления LinkButton.To enable sorting in the GridView, simply check the Enable Sorting checkbox in the GridView s smart tag, which sets the GridView s AllowSorting property to true and causing the header text for each column to be rendered as a LinkButton. Когда пользователь щелкает одну из заголовков LinkButton, происходит обратная передача и выполняются следующие действия:When the end user clicks on one of the header LinkButtons, a postback ensues and the following steps transpire:

  1. GridView обновляет свойствоSortExpression на значение SortExpression поля, для которого была нажата ссылка заголовкаThe GridView updates its SortExpression property to the value of the SortExpression of the field whose header link was clicked
  2. ObjectDataSource вызывает метод GetProductsPagedAndSorted BLL, передавая свойство GridView s SortExpression в качестве значения для метода s sortExpression входного параметра (вместе с соответствующими значениями входных параметров startRowIndex и maximumRows).The ObjectDataSource invokes the BLL s GetProductsPagedAndSorted method, passing in the GridView s SortExpression property as the value for the method s sortExpression input parameter (along with the appropriate startRowIndex and maximumRows input parameter values)
  3. BLL вызывает метод DAL GetProductsPagedAndSortedThe BLL invokes the DAL s GetProductsPagedAndSorted method
  4. DAL выполняет GetProductsPagedAndSorted хранимую процедуру, передавая параметр @sortExpression (вместе со значениями входных параметров @startRowIndex и @maximumRows).The DAL executes the GetProductsPagedAndSorted stored procedure, passing in the @sortExpression parameter (along with the @startRowIndex and @maximumRows input parameter values)
  5. Хранимая процедура возвращает соответствующее подмножество данных BLL, который возвращает его в ObjectDataSource; Затем эти данные привязываются к GridView, подготавливаются к просмотру в формате HTML и отправляются конечному пользователю.The stored procedure returns the appropriate subset of data to the BLL, which returns it to the ObjectDataSource; this data is then bound to the GridView, rendered into HTML, and sent down to the end user

На рис. 7 показана первая страница результатов при сортировке по UnitPrice в возрастающем порядке.Figure 7 shows the first page of results when sorted by the UnitPrice in ascending order.

результаты сортируются по UnitPriceThe Results are Sorted by the UnitPrice

Рис. 7. Результаты сортируются по UnitPrice (щелкните, чтобы просмотреть изображение с полным размером)Figure 7: The Results are Sorted by the UnitPrice (Click to view full-size image)

Хотя текущая реализация может правильно отсортировать результаты по названию продукта, имени категории, количеству на единицу и цене за единицу, попытка упорядочить результаты по имени поставщика приводит к возникновению исключения времени выполнения (см. рис. 8).While the current implementation can correctly sort the results by product name, category name, quantity per unit, and unit price, attempting to order the results by the supplier name results in a runtime exception (see Figure 8).

Попытка отсортировать результаты по поставщику приводит к возникновению следующего исключения среды выполнения

Рис. 8. попытка отсортировать результаты по поставщику приводит к возникновению следующего исключения среды выполненияFigure 8: Attempting to Sort the Results by the Supplier Results in the Following Runtime Exception

Это исключение возникает, поскольку SortExpression GridView s SupplierName BoundField имеет значение SupplierName.This exception occurs because the SortExpression of the GridView s SupplierName BoundField is set to SupplierName. Однако имя поставщика в таблице Suppliers на самом деле называется CompanyName мы назвали имя этого столбца как SupplierName.However, the supplier s name in the Suppliers table is actually called CompanyName we have been aliased this column name as SupplierName. Однако предложение OVER, используемое функцией ROW_NUMBER(), не может использовать псевдоним и должно использовать фактическое имя столбца.However, the OVER clause used by the ROW_NUMBER() function cannot use the alias and must use the actual column name. Поэтому измените SupplierName BoundField s SortExpression SupplierName на CompanyName (см. рис. 9).Therefore, change the SupplierName BoundField s SortExpression from SupplierName to CompanyName (see Figure 9). Как показано на рис. 10, после этого изменения результаты могут быть отсортированы по поставщику.As Figure 10 shows, after this change the results can be sorted by the supplier.

Измените SortExpression SupplierName BoundField s на CompanyName.

Рис. 9. изменение SupplierName BoundField s SortExpression на CompanyNameFigure 9: Change the SupplierName BoundField s SortExpression to CompanyName

теперь результаты можно отсортировать по поставщикуThe Results Can Now Be Sorted by Supplier

Рис. 10. Теперь результаты можно сортировать по поставщикам (щелкните, чтобы просмотреть изображение с полным размером)Figure 10: The Results Can Now Be Sorted by Supplier (Click to view full-size image)

СводкаSummary

Реализация пользовательского разбиения по страницам, которую мы рассматривали в предыдущем руководстве, требовала, чтобы порядок сортировки результатов был указан во время разработки.The custom paging implementation we examined in the preceding tutorial required that the order by which the results were to be sorted be specified at design time. Вкратце, это означало, что реализация пользовательского разбиения по страницам, которую мы реализовали, не может в то же время предоставить возможности сортировки.In short, this meant that the custom paging implementation we implemented could not, at the same time, provide sorting capabilities. В этом учебнике мы преодолел все испытания это ограничение, расширив хранимую процедуру из первого, чтобы включить входной параметр @sortExpression, по которому можно сортировать результаты.In this tutorial we overcame this limitation by extending the stored procedure from the first to include a @sortExpression input parameter by which the results could be sorted.

После создания этой хранимой процедуры и создания новых методов в слоях DAL и BLL мы смогли реализовать GridView, которое предлагает как сортировку, так и настраиваемое разбиение на страницы, настроив ObjectDataSource для передачи свойства Current SortExpression в GridView s в SelectMethodBLL.After creating this stored procedure and creating new methods in the DAL and BLL, we were able to implement a GridView that offered both sorting and custom paging by configuring the ObjectDataSource to pass in the GridView s current SortExpression property to the BLL SelectMethod.

Поздравляем с программированием!Happy Programming!

Об автореAbout the Author

Скотт Митчелл, автор семи книг по ASP/ASP. NET и основатель 4GuysFromRolla.com, работал с веб-технологиями Майкрософт с 1998.Scott Mitchell, author of seven ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Скотт работает как независимый консультант, преподаватель и модуль записи.Scott works as an independent consultant, trainer, and writer. Его последняя книга — Sams обучать себя ASP.NET 2,0 за 24 часа.His latest book is Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Он доступен по адресу mitchell@4GuysFromRolla.com.He can be reached at mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.or via his blog, which can be found at http://ScottOnWriting.NET.

Специальная благодарностьSpecial Thanks To

Эта серия руководств была рассмотрена многими полезными рецензентами.This tutorial series was reviewed by many helpful reviewers. Специалист по интересу для этого руководства был Карлос Сантос.Lead reviewer for this tutorial was Carlos Santos. Хотите ознакомиться с моими будущими статьями MSDN?Interested in reviewing my upcoming MSDN articles? Если это так, расположите строку в mitchell@4GuysFromRolla.com.If so, drop me a line at mitchell@4GuysFromRolla.com.