ADO.NET Data Services 1.5: server driven paging

Мы продолжаем рассматривать новые возможности ADO.NET Data Services 1.5 и сегодня мы посмотрим возможность принудительной разбивки данных на страницы.

В первой версии Astoria возможность разбивки данных на страницы уже присутствовала. Для этих целей можно было построить запрос с помощью конструкций Take/Skip. Изменяя значения этих параметров можно было получить постраничный доступ к данным с клиента. Тем не менее, при обращении к коллекции без параметров сервис возвращал полностью всю коллекцию. Описанное поведение кажется вполне логичным, но оно не всегда является желательным. К примеру, если в коллекции содержится большое количество объектов, то обращение к такой коллекции непременно повлечет повышенную нагрузку на сервер, а клиент получит задержку при обращении к сервису. Поэтому в версии 1.5 было принято решение о добавлении возможности принудительной разбивки на страницы.

Для включения описанной возможности необходимо определить дополнительное поведение при конфигурировании сервиса. В частности нам необходим метод SetEntitySetPageSize(), который позволяет определить размер страницы для каждой коллекции. Этот метод принимает два параметра — имя коллекции и размер страницы. Если необходимо определить размер для всех коллекций, то в качестве имени коллекции необходимо использовать *.

public class WebDataService : DataService<NorthwindEntities>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
    
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        config.SetEntitySetPageSize("Categories", 5);
    }
}

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

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

http://.../WebDataService.svc/Categories?$skiptoken=5

Данная функциональность также поддерживается и в рамках клиентского прокси. При обычном обращении к коллекции клиенту будет выдано только указанное число объектов. Для обращения к остальным страницам необходимо использовать метод Skip().

var client = new NorthwindEntities(new Uri(@"..."));
var q = from c in client.Categories.Skip(2)
        select c;

foreach (var item in q)
{
    // ...
}

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

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