Статьи

Изучение параметров запроса OData Web API

Как я упоминал в посте об операциях CRUD с использованием веб-API , в OData есть много вариантов запросов. Полный список стандартных вариантов запросов можно найти на официальном сайте OData . В этой статье мы рассмотрим параметры запросов, поддерживаемые веб-API, а также увидим, как использовать эти параметры запросов от клиентов .NET через запросы LINQ.

Поддержка запросов в Web API Data может быть включена двумя следующими способами:

  • На уровне метода, установив атрибут Queryable в методе Get
[Queryable]
public IQueryable<Customer> Get()
{
    .....
}
  • При запуске приложения, с помощью вызова EnableQuerySupport метода на HttpConfiguration объекта

GlobalConfiguration.Configuration.EnableQuerySupport();

Чтобы иметь возможность изучить больше вариантов, мы будем использовать
базу данных
Northwind . Создайте модель данных объекта ADO.NET со следующими таблицами:

  • Клиенты
  • заказы
  • Сотрудник

Давайте сделаем эти объекты доступными для конечной точки OData Web API, добавив их в модель EDM. Следующие заявления выполняют это:

var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Customer>("Customers");
modelBuilder.EntitySet<Order>("Orders");
modelBuilder.EntitySet<Employees>("Employees");
Microsoft.Data.Edm.IEdmModel model = modelBuilder.GetEdmModel();
GlobalConfiguration.Configuration.Routes.MapODataRoute("ODataRoute", "odata", model);

Добавьте контроллер Web API с именем
CustomersController и измените код следующим образом:

public class CustomersController : ODataController
{
    NorthwindEntities context = new NorthwindEntities();
 
    public IQueryable<Customer> Get()
    {
        return context.Customers;
    }
}

Теперь мы готовы проверить сервис. Запустите проект и измените URL в браузере:

 localhost:<port-no>/odata

Вы должны увидеть записи для каждой коллекции сущностей, которую мы добавили.
Теперь, когда служба запущена и работает, создайте клиентский проект и добавьте ссылку на службу только что созданной службы (вы можете обратиться к моей публикации по
использованию OData из публикации клиентов .NET для настройки клиента). Также создайте объект-контейнер, передав URL-адрес службы OData Web API.
Теперь, когда у нас есть служба и клиент готов, давайте начнем изучать различные варианты запроса службы.
$ фильтра:

Все параметры запроса OData основаны на строке запроса. $ filter является самым основным и самым мощным из них. Как следует из названия, $ filter используется для выбора данных из коллекции на основе некоторых условий. Типовые условия варьируются от простого равного оператору до операций фильтрации строк и дат.

Как
мы уже знаем , следующий URL извлекает информацию обо всех клиентах в базе данных Northwind:

    http://localhost:<port-no>/odata/Customers

Давайте добавим условие для получения сведений о клиентах с названием «Владелец». Следующий URL-адрес получает значения для нас:

    http://localhost:<port-no>/odata/Customers?$filter=ContactTitle eq 'Owner'

Этот фильтр можно применить из .NET-клиента с помощью оператора LINQ Where. Следующий запрос:

var filteredCustomers = container.Customers.Where(c => c.ContactTitle == "Owner");

Вышеуказанный запрос не запускается в памяти. Вместо этого он генерирует вышеуказанный URL, анализируя выражения, переданные в операторы LINQ. Сгенерированный URL можно просмотреть во время отладки. На следующем снимке экрана показан URL-адрес, созданный с помощью указанного выше запроса.
Как мы видим, он совпадает с URL-адресом, который мы ввели вручную.
Чтобы выбрать всех клиентов, у которых есть контакт с Ana, в начале их
ContactName можно выбрать, используя следующий URL:

 http://localhost:<port-no>/odata/Customers?$filter=startswith(ContactName,'Ana') eq true

Приведенный выше запрос использует функцию OData
startwith () для сравнения начальных букв значения поля. Соответствующий запрос LINQ:

container.Customers.Where(c => c.ContactName.StartsWith("Ana"))

Точно так же
endwith () может использоваться для сравнения суффикса строки. Мы также можем проверить, содержится ли строка в поле, используя
функцию
substringof () .

 http://localhost:<port-no>/odata/Customers?$filter=substringof('ill',CompanyName)%20eq%20true

Соответствующий запрос LINQ:

container.Customers.Where(c => c.CompanyName.Contains("ill"))

Чтобы получить список всех клиентов с длиной их имен больше 10 и меньше 20, URL:

 http://localhost:<port-no>/odata/Customers?$filter=length(ContactName) gt 10 and length(ContactName) lt 20

Вы должны уже угадать запрос LINQ, чтобы достичь того же.

container.Customers.Where(c => c.ContactName.Length > 10 && c.ContactName.Length < 20)

$ filter поддерживает запросы на основе чисел, дат и даже типов проверки. Вы можете получить полный список на
официальном сайте для OData .

$ orderby:

результат можно упорядочить по полю с помощью оператора $ orderby. Синтаксис указания оператора такой же, как и у оператора $ filter. Следующий URL и запрос LINQ извлекают сведения о клиентах с названиями стран, упорядоченных в порядке возрастания:

    http://localhost:<port-no>/odata/Customers?$orderby=Country 
container.Customers.OrderBy(c => c.Country)

Чтобы сделать порядок по убыванию, нам просто нужно указать ключевое слово desc в конце вышеуказанного URL.

$ top и $ skip

Коллекции серверов можно разделить на страницы от клиента с помощью операторов $ top и $ skip. Этим операторам присваиваются номера, которые указывают количество записей, которые должны быть выбраны сверху, или количество записей, которые должны быть пропущены с начала коллекции.

После запроса URL и LINQ выберите первых 10 клиентов в таблице «Клиенты».


    http://localhost:<port-no>/odata/Customers?$top=10
container.Customer.Take(10)

Синтаксис использования $ skip аналогичен синтаксису $ top, так как $ skip также ожидает, что число будет передано. И $ skip, и $ top могут использоваться вместе для извлечения данных из нескольких блоков. Следующий URL выбирает 10 клиентов, начиная с индекса 40.

    http://localhost:<port-no>/odata/Customers?$skip=40&$top=10
container.Customers.Skip(40).Take(10)

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

Пейджинг на стороне сервера.

Пейджинг можно включить на сервере с помощью
свойства
PageSize атрибута Queryable . Следующий фрагмент применяет страницу размером 20 при возврате коллекции клиентов:

[Queryable(PageSize=20)]
public IQueryable<Customer> Get()
{
    return context.Customers;
}

Он также может применяться глобально ко всем наборам сущностей, устанавливая свойство для объекта конфигурации при запуске приложения следующим образом:

IActionFilter filter = new QueryableAttribute() { PageSize=20 };
config.EnableQuerySupport(filter);

Если вы нажмете URL, чтобы получить все клиенты в своем любимом браузере после применения вышеуказанных изменений, вы сможете увидеть только 20 записей со ссылкой на следующий набор в конце набора результатов, как показано на следующем снимке экрана:
Поскольку URL передается как свойство объекта JSON, его можно легко извлечь в любом клиенте JavaScript для отправки запроса на следующий набор значений. Но это немного сложно с клиентом .NET. Запрос LINQ коллекции, написанный на клиенте, должен быть преобразован в
DataServiceCollection, чтобы получить URL следующего запроса. Это показано ниже:

var firstSetOfCustomers = new DataServiceCollection<Customer>(container.Customers);
var nextSetOfCustomers = new DataServiceCollection<Customer>(container.Execute<Customer>(firstSetOfCustomers.Continuation.NextLinkUri));

Количество записей на всех страницах можно получить, используя опцию запроса $ inlinecount в приведенном выше запросе.

    http://localhost:<port-no>/odata/Customers?$inlinecount=allpages
var firstSetOfCustomers = new DataServiceCollection<Customer>(container.Customers.IncludeTotalCount());

$ expand:

команда ASP.NET Web API добавила поддержку параметров $ expand и $ select в своем последнем выпуске версии 5.0.0-rc1. Он встроен в
Visual Studio 2013 Preview . В Visual Studio 2012
пакет NuGet можно обновить до предварительной версии.

$ expand используется для включения значений навигационных свойств набора запрашиваемых сущностей. Интересной частью является то, что результаты навигационных свойств внутреннего набора сущностей также могут быть включены в набор результатов. После запроса URL и LINQ извлекаются сведения о клиентах, их заказах и сведениях о сотруднике, разместившем заказ.

    http://localhost:<port-no>/odata/Customers?$expand=Orders/Employee
container.Customers.Expand("Orders/Employee");

Вышеупомянутый запрос перемещается до двух уровней вниз по набору сущностей. Глубиной навигации можно управлять с
помощью свойства
MaxExpansionDepth атрибута
Queryable .

[Queryable(MaxExpansionDepth=1)]
public IQueryable<Customer> Get()
{
    return context.Customers;
}

Эта конфигурация может быть применена к
объекту
HttpConfiguration при запуске приложения.

IActionFilter filter = new QueryableAttribute() { MaxExpansionDepth=1 };
config.EnableQuerySupport(filter);

После применения вышеуказанных изменений клиент не может перейти на более чем один уровень вниз по набору сущностей.

$ select:

клиент может запросить прогнозируемые результаты в зависимости от своих потребностей. Список запрашиваемых свойств может быть указан при запросе службы, чтобы получить только эти свойства. Ниже приведены пример URL и запрос LINQ:

    http://localhost:<port-no>/odata/Customers?$select=CustomerID,ContactName
container.Customers.Select(c => new { ID = c.CustomerID, Name = c.ContactName });

Обновление. В моем сообщении о  запросе OData через веб-API с помощью Breeze JS  все вышеперечисленные URL-адреса выражены как Breeze Queries.

Удачного кодирования!