OData — протокол открытых данных
OData
Что такое OData?
OData (Open Data Protocol, «протокол открытых данных») — это открытый стандарт для создания и использования RESTful API, ориентированных на работу со структурированными данными как с единой моделью сущностей. Клиент обращается к ресурсам по HTTP, а сервер может на лету отфильтровать, отсортировать, развернуть связи и вернуть только нужные поля — без того, чтобы для каждой комбинации параметров проектировать отдельный эндпоинт.
OData не заменяет HTTP и не конкурирует с JSON как форматом: он надстраивается над REST, добавляя согласованные правила адресации ресурсов, описания модели данных (метаданные) и системных опций запроса — $filter, $select, $expand и других.
Официальная документация и экосистема Microsoft: OData на Microsoft Learn. Спецификация поддерживается консорциумом OASIS; актуальные версии протокола — OData 4.0 и 4.01.
Простая аналогия: обычный REST API — это меню с фиксированными блюдами («список пользователей», «пользователь по id», «активные пользователи за месяц» — три разных URL). OData ближе к SQL поверх HTTP: один ресурс Users, а «нарезка» данных задаётся в строке запроса.
OData - стандарт запросов к REST-данным
В середине 2000-х корпоративным системам нужен был способ отдавать данные множеству клиентов (веб, десктоп, отчёты, интеграции) без взрыва числа методов API. Microsoft предложила протокол в 2007 году; с 2012 года OData развивается как открытый стандарт OASIS, а не как закрытая технология одного вендора.
Идея: описать модель данных (сущности, свойства, связи, операции) один раз, опубликовать сервисный корень (service root) и позволить клиентам комбинировать стандартные опции запроса. Так снижается дублирование контрактов и упрощается интеграция между продуктами разных команд.
Где OData используется
| Область | Примеры |
|---|---|
| Корпоративные ERP/CRM | Microsoft Dynamics 365, SAP (OData-сервисы), интеграции с учётными системами |
| Платформа Microsoft | SharePoint REST/OData, Azure API Management, отчётность Power BI к OData-источникам |
| Разработка на .NET | ASP.NET Core OData, Microsoft.OData.Client, Web API с пакетом Microsoft.AspNetCore.OData |
| Отечественные продукты | Публикация данных из 1С через OData для витрин и внешних систем |
| Универсальные клиенты | Excel Power Query, Postman, браузерные REST-клиенты, генераторы кода по $metadata |
OData особенно уместен, когда потребителей много, набор полей и фильтров непредсказуем, а данные уже лежат в реляционной или объектной модели (таблицы, сущности EF, справочники конфигурации).
Как устроен OData-сервис
Сервисный корень и наборы сущностей
OData-сервис публикуется с корневого URL (service root), например:
https://services.example.com/odata/v1/
По этому адресу клиент получает описание наборов сущностей (entity sets) — коллекций, с которыми можно работать, по смыслу близких к таблицам или ресурсам REST:
GET https://services.example.com/odata/v1/
Типичные пути к данным:
GET .../odata/v1/Products — коллекция
GET .../odata/v1/Products(42) — одна сущность по ключу
GET .../odata/v1/Categories(3)/Products — связанная коллекция
Идентификация сущности в URL может быть в скобках Products(42) или в сегменте пути — в зависимости от версии и настроек сервиса; смысл один: стабильный адрес ресурса в терминах модели, а не произвольное имя метода.
Метаданные модели ($metadata)
Ключевое отличие от «голого» REST — документ метаданных (Conceptual Schema Definition Language, CSDL), обычно доступный по:
GET .../odata/v1/$metadata
В нём описаны:
- типы сущностей и сложных типов;
- свойства, ключи, обязательность;
- навигационные свойства (связи «один-ко-многим», «многие-ко-многим»);
- действия (actions) и функции (functions).
Клиенты и инструменты (Power Query, генераторы прокси) читают $metadata и понимают модель без отдельного PDF-контракта. Для человека это XML; для машины — основа типобезопасных клиентов.
HTTP и форматы представления
OData опирается на HTTP:
| Операция | HTTP | Пример смысла |
|---|---|---|
| Чтение коллекции или сущности | GET | Список заказов, заказ по id |
| Создание | POST | Новая запись в наборе |
| Полная замена | PUT | Обновление всех полей |
| Частичное обновление | PATCH | Изменение отдельных полей |
| Удаление | DELETE | Удаление сущности |
Тело запросов и ответов чаще всего в JSON (application/json); в спецификации также предусмотрен Atom/XML. Заголовок Accept и опция $format уточняют представление.
Поток обработки запроса:
Системные опции запроса (query options)
Системные опции — параметры строки запроса, которые управляют объёмом, составом и порядком возвращаемых данных. В OData 4.x имена опций могут начинаться с $ (в 4.01 поддерживается и без префикса, регистронезависимо для совместимости).
| Опция | Назначение |
|---|---|
$filter | Фильтрация коллекции (предикат по полям и связям) |
$select | Выбор только указанных свойств |
$expand | «Подгрузка» связанных сущностей в одном ответе |
$orderby | Сортировка |
$top / $skip | Постраничная выборка (лимит и смещение) |
$count | Включить или запросить только количество элементов |
$search | Полнотекстовый поиск (семантика зависит от реализации сервиса) |
$compute | Вычисляемые поля в проекции (OData 4.01) |
Подробные правила и примеры: Обзор опций запроса, Использование опций.
$filter — фильтрация на сервере
Вместо эндпоинта GET /users?status=active&minAge=18 клиент пишет единый ресурс и выражение:
GET .../People?$filter=FirstName eq 'Иван' and Age ge 18
Поддерживаются сравнения (eq, ne, gt, ge, …), логика (and, or, not), функции (contains, startswith, year, …), обход связей (Department/Name eq 'IT'). Сервер обязан интерпретировать фильтр по модели; необоснованные поля отклоняются или игнорируются согласно политике безопасности.
$select и $expand — экономия трафика
Только нужные поля:
GET .../Products?$select=Name,Price
Связанные сущности «в одном заходе»:
GET .../Orders(1001)?$expand=Customer,Lines
Комбинация: развернуть заказчика, но у него взять только имя и город:
GET .../Orders?$expand=Customer($select=Name,City)
Это прямой аналог JOIN + проекции в SQL, но выраженный в URL — удобно для UI, которому на списке нужны разные «срезы» данных.
Пагинация
GET .../Products?$orderby=Name&$top=20&$skip=40
Сервис может вернуть @odata.nextLink — URL следующей страницы, чтобы клиент не собирал смещения вручную при больших объёмах.
$count
GET .../Products/$count
GET .../Products?$count=true&$filter=Price gt 1000
Позволяет получить число элементов без полной выгрузки коллекции.
Действия и функции
Помимо CRUD над сущностями, OData описывает:
- Functions — операции без побочных эффектов (как чистые функции), вызываются через
GET, могут участвовать в$filter/$orderby. - Actions — операции с побочными эффектами (списание, утверждение документа, массовая операция), обычно через
POST.
Пример вызова функции (схематично):
GET .../Products/Model.GetFeaturedProducts()
Action может принимать параметры в теле POST. Так протокол совмещает ресурсную модель и бизнес-операции, не ломая REST-транспорт.
Версии протокола
| Версия | Заметки |
|---|---|
| OData 2.0 / 3.0 | Широко в legacy (SharePoint, старые .NET-сервисы); опции вроде $inlinecount |
| OData 4.0 / 4.01 | Текущая основа; улучшенная типизация, $compute, уточнённые правила URL |
| OData 4.02 | Развитие стандарта OASIS; при внедрении сверяйтесь с документом протокола |
При интеграции всегда уточняйте версию сервиса и набор поддерживаемых опций: сервер может не реализовать $search или $expand на глубину больше N.
OData и «обычный» REST
| Критерий | REST (типичный) | OData |
|---|---|---|
| Контракт | OpenAPI/Swagger, описание вручную | $metadata + соглашения протокола |
| Фильтрация | Отдельные query-параметры на каждый сценарий | Единый язык $filter |
| Связи | Несколько запросов или специальные DTO | $expand по навигационным свойствам |
| Сложность сервера | Ниже, полный контроль эндпоинтов | Выше: парсер запросов, безопасность, производительность |
| Кэширование | Проще для простых GET | Сложнее из-за комбинаций опций |
| Клиенты | Универсальны | Выигрывают типизированные OData-клиенты |
OData не обязателен для каждого API. Его выбирают, когда много ад hoc запросов к одной модели данных (отчёты, интеграции, админки). Для узкого мобильного API с фиксированными экранами чаще достаточно простого REST или GraphQL.
Безопасность и эксплуатация
Свободный $filter и $orderby — это по сути пользовательский запрос к данным. Риски:
- Производительность — тяжёлые фильтры без индексов нагружают СУБД;
- Утечка полей —
$selectне должен обходить права на свойства; - Инъекции — реализация должна параметризовать запросы к БД, а не склеивать SQL из строки URL.
На практике ограничивают глубину $expand, белый список полей в $filter, лимиты $top, аутентификацию (OAuth 2.0, API keys) и авторизацию на уровне строк. Подробнее про развёртывание и hardening: раздел Security на Microsoft Learn.
Пример на C# (клиент)
Для .NET существует клиентская библиотека, работающая с IQueryable-подобным API:
var context = new Container(new Uri("https://services.example.com/odata/v1/"));
var query = context.Products
.Where(p => p.Price < 100)
.OrderBy(p => p.Name)
.Take(10);
foreach (var product in query)
{
Console.WriteLine($"{product.Name}: {product.Price}");
}
На сервере ASP.NET Core OData подключает те же опции к контроллерам или minimal API, транслируя $filter в LINQ и далее в SQL через EF Core.
Связанные материалы энциклопедии: API, HTTP, Веб-сервисы, SOAP, 1С: интеграция.
Полезные ссылки
- Документация OData (Microsoft Learn, RU)
- Что такое OData?
- Модель данных OData
- Опции запроса — обзор
- OData на ASP.NET Core
- Спецификация OASIS OData 4.01
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Интеграция - это когда две программы умеют разговаривать друг с другом и делать общее дело. Выбор модели взаимодействия определяет архитектурные свойства системы — отзывчивость, устойчивость к сбоям, сложность отладки и масштабируемость. Интеграционные потоки данных - как моделируются маршруты сообщений, преобразования и оркестрация обмена между системами. Что такое интеграционная авторизация, API-ключи и как с этим работать. Управление сессиями в распределённых системах - согласование состояния между сервисами, паттерны саг и компенсационные операции. История интеграционных технологий - эволюция от RPC и CORBA к современным API, шинам сообщений и событийной архитектуре. Веб-сервис - это программа, которая живёт на сервере и отвечает на запросы других программ через интернет. Мы её не видим (нет никакой кнопки или картинки), но наше приложение с ней разговаривает. Модель запрос-ответ в интеграции систем - как сервисы принимают входные события, обрабатывают их и возвращают результат внешним участникам. API как контракт и способы вызова; REST — архитектурный стиль, не протокол; терминология, ограничения Филдинга, OpenAPI и обзор других стилей API. HTTP-запрос состоит из трёх частей - стартовая строка, заголовок и тело запроса. Асинхронная коммуникация между сервисами - когда отправитель не ждёт немедленного ответа и как это повышает устойчивость системы. Реактивные взаимодействия фокусируются на обмене событиями в режиме реального времени. Системы реагируют на события по мере их возникновения, обеспечивая непрерывный поток данных.Интеграция
Типы взаимодействия между системами
Интеграционные потоки данных
Авторизация в интеграционных сценариях
Управление сессиями в распределённых системах
История развития интеграционных технологий
Веб-сервисы
Модель запрос-ответ в сетевом взаимодействии
API - интерфейсы прикладного программирования
HTTP как основа веб-интеграций
Асинхронная коммуникация между сервисами
Реактивные системы и потоки данных