Управление контекстом службы данных (службы WCF Data Services)

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

Параметры слияния и разрешение идентификаторов

При исполнении DataServiceQuery<TElement> сущности в канале ответа материализуются в объекты. Дополнительные сведения см. в разделе Материализация объектов (службы WCF Data Services). Способ материализации сущностей в ответном сообщении в объекты выбирается в зависимости от разрешения идентификаторов и параметра слияния, при котором был произведен запрос. Когда несколько запросов или требований загрузки выполняются в области одного контекста DataServiceContext, клиент Службы WCF Data Services отслеживает только один экземпляр объекта, имеющий определенное значение ключа. Этот ключ, который используется для разрешения идентификаторов, однозначно определяет сущность.

По умолчанию клиент материализует значение в канале ответа в объект только для сущностей, еще не отслеживаемых в контексте DataServiceContext. Это означает, что изменения в объектах, уже находящихся в кэше, не перезаписываются. Это поведение управляется указанием значения параметра MergeOption для запросов и операций загрузки. Этот параметр указывается установкой свойства MergeOption в DataServiceContext. Значение параметра слияния по умолчанию равно AppendOnly. В этом случае материализуются только объекты для еще неотслеживаемых сущностей, то есть существующие объекты не перезаписываются. Еще один способ предотвратить перезапись изменений объектов в клиенте при получении обновлений из службы данных состоит в указании параметра PreserveChanges. При указании параметра OverwriteChanges значения объектов в клиенте заменяются новейшими значениями из записей в канале ответа, даже если в эти объекты уже были внесены изменения. При использовании параметра слияния NoTracking DataServiceContext не может отправлять изменения, внесенные в объекты клиента, в службу данных. При выборе этого параметра, изменения всегда перезаписываются значениями из службы данных.

Управление параллелизмом

OData поддерживает оптимистичный параллелизм, позволяющий службе данных обнаруживать конфликты обновлений. Поставщик службы данных можно настроить таким образом, что служба данных будет проверять наличие изменений в сущностях с помощью токена параллелизма. Этот токен включает одно или несколько свойств типа сущности, проверяемых службой данных для определения, был ли ресурс изменен. Токены параллелизма, указанные в заголовке eTag запросов и ответов службы данных, управляются клиентом Службы WCF Data Services. Дополнительные сведения см. в разделе Обновление службы данных (службы WCF Data Services).

Объект DataServiceContext отслеживает изменения, внесенные в объекты, указанные вручную с помощью методов AddObject, UpdateObject и DeleteObject или с помощью объекта DataServiceCollection<T>. При вызове метода SaveChanges клиент отправляет изменения назад службе данных. Метод SaveChanges может завершиться ошибкой, если изменения данных, произведенные клиентом, вступают в конфликт с изменениями, произведенными службой данных. В этом случае необходимо запросить сущности повторно, чтобы получить обновленные данные. Чтобы переписать изменения в службе данных, выполните запрос с использованием параметра слияния PreserveChanges. При повторном вызове метода SaveChanges изменения, произведенные в клиенте, будут внесены в службе данных, если в службе данных не производилось других изменений в ресурсах.

Сохранение изменений

Изменения отслеживаются в экземпляре DataServiceContext, но не отправляются на сервер немедленно. После завершения изменений для указанного действия вызовите метод SaveChanges, чтобы передать все изменения в службу данных. По завершении операции SaveChanges возвращается объект DataServiceResponse. Объект DataServiceResponse включает последовательность объектов OperationResponse, которые в свою очередь содержат последовательность экземпляров EntityDescriptor или LinkDescriptor, представляющих сохраненные или ожидаемые изменения. Когда сущность создается или изменяется в службе данных, объект EntityDescriptor включает ссылку на обновленную сущность, включая все значения свойств, сформированные сервером, такие как сформированное значение ProductID в предыдущем примере. Клиентская библиотека автоматически обновляет объект .NET Framework с учетом этих новых значений.

Для успешного выполнения операций вставки и обновления свойству состояния объекта EntityDescriptor или LinkDescriptor, связанного с операцией, присваивается значение Unchanged, а новые значения добавляются с помощью OverwriteChanges.

Если операция вставки, обновления или удаления завершается с ошибкой, состояние сущности остается таким же, как до вызова метода SaveChanges, а свойству Error объекта OperationResponse присваивается значение DataServiceRequestException, содержащее сведения об ошибке. Дополнительные сведения см. в разделе Обновление службы данных (службы WCF Data Services).

Управление запросами

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

Установка заголовка Prefer для операций изменения

По умолчанию полезные данные сообщения возвращаются только в ответ на запрос POST с целью создания новой сущности. В этом случае новая сущность возвращается в полезных данных. Это означает, что при обновлении объектов, обновленная сущность не возвращается в полезной нагрузке или ответном сообщении. Однако, согласно протоколу OData, клиент может использовать заголовок Prefer, чтобы запросить изменение этого поведения, выбираемого по умолчанию. Заголовок Prefer в запросе POST, PUT, PATCH или MERGE формируется DataServiceContext на основе значения DataServiceResponsePreference, установленного в свойстве AddAndUpdateResponsePreference. В следующей таблице показаны параметры заголовка Prefer и соответствующее ответное поведение.

Значение заголовка Prefer

Значение AddAndUpdateResponsePreference

Ответное поведение

Не включено в запрос. Это поведение по умолчанию.

None

Ответная полезная нагрузка возвращается только для запросов POST, но не для запросов PUT, PATCH и MERGE.

return-content

IncludeContent

Ответная полезная нагрузка возвращается для всех запросов на изменение.

return-no-content

NoContent

Ответная полезная нагрузка не возвращается для любых запросов. Для запроса POST служба данных также включает заголовок DataServiceId в ответе. Этот заголовок используется для передачи значения ключа вновь созданной сущности.

Примечание

Даже если служба данных поддерживает версию протокола OData, который поддерживает заголовок Prefer, служба данных может не соблюдать такие виды предпочтений обработки запросов.

Задание метода HTTP для обновлений

По умолчанию клиентская библиотека платформы .NET Framework отправляет обновления созданным сущностям в качестве запросов MERGE. В OData запрос MERGE обновляет выбранные свойства сущности, однако клиент всегда включает все свойства в запрос MERGE, даже свойства, которые не изменились. Протокол OData также поддерживает отправку запросов PUT и PATCH для обновления сущностей. В запросе PUT существующая сущность заменяется новым экземпляром сущности с клиентскими значениями свойств. Запросы PATCH обрабатываются таким же образом, как запросы MERGE, однако PATCH — стандартное действие HTTP, тогда как MERGE определяется в OData. Это поведение обновления задается путем предоставления либо значения ReplaceOnUpdate, чтобы использовать запросы PUT, либо значения PatchOnUpdate, чтобы использовать запросы PATCH как параметры при вызове SaveChanges(SaveChangesOptions).

Примечание

Поведение запроса PUT будет иным, чем у запроса MERGE или PATCH, если клиенту неизвестно обо всех свойствах сущности.Такое может иметь место во время проекции типа сущности в новый тип на клиенте.Это также может иметь место при добавлении новых свойств в сущность в модели сервисных данных, если свойство IgnoreMissingProperties в контексте DataServiceContext имеет значение true, то есть система будет пропускать такие клиентские ошибки сопоставления.В таких случаях запрос PUT сбросит значения всех неизвестных клиенту свойств по умолчанию.

POST-туннелирование

По умолчанию клиентская библиотека отправляет запросы create, read, update и delete в службу OData с помощью соответствующих методов HTTP PUT/MERGE/PATCH и DELETE. Поддерживаются основные принципы REST (передачи репрезентативных состояний). Однако не каждая реализация веб-сервера поддерживает полный набор методов HTTP. В некоторых случаях поддерживаемые методы ограничиваются лишь GET и POST. Это может произойти, когда посредник, например межсетевой экран, блокирует запросы с некоторыми методами. Поскольку методы GET и POST чаще всего поддерживаются, OData обеспечивает возможность выполнения любых неподдерживаемых методов HTTP с помощью запроса POST. Известный как метод туннелирования или POST-туннелирование, он позволяет клиенту отправить запрос POST с фактическим методом, который задан в пользовательском заголовке X-HTTP-Method. Чтобы включить POST-туннелирование для запросов, задайте для свойства UsePostTunneling на экземпляре DataServiceContext значение true.

Разрешение базовых URI наборов сущностей

По умолчанию клиент предполагает, что все наборы сущностей, также известные как коллекции, используют один общий базовый URI. Этот базовый URI определяется свойством BaseUri в DataServiceContext. Однако протокол OData позволяет службе данных представлять наборы сущностей как каналы, которые имеют различные базовые идентификаторы URI. Чтобы иметь возможность обрабатывать наборы сущностей с различными базовыми идентификаторами URI, клиент позволяет зарегистрировать делегата с DataServiceContext, который может использоваться для разрешения базовых идентификаторов URI различных наборов сущностей. Этот делегат — метод, который принимает строку (имя набора сущностей) и возвращает Uri (базовый URI для указанного набора сущностей). Этот сопоставитель зарегистрирован с DataServiceContext путем назначения свойству ResolveEntitySet. Образец реализации сопоставителя может при создании контекста прочитать сведения о коллекциях, которые возвращаются корневой службой данных, и сохранить значения базового URI для каждой коллекции в словаре. Этот словарь может затем использоваться сопоставителем для возврата URI для определенного набора сущностей. Более полный пример, включая образцы кода, см. в публикации Entity Set Resolver.

Требования к управлению версиями

Поведения DataServiceContext имеют следующие требования к управлению версиями протокола OData.

  • Для поддержки заголовка Prefer и запросов PATCH необходимо, чтобы клиент и служба данных поддерживали версию 3.0 протокола OData и более поздние версии.

  • Для поддержки распознавателей наборов сущностей необходима версия клиентской библиотеки Службы WCF Data Services, вошедшая в версию Data Framework, или более поздняя версия.

Дополнительные сведения см. в разделе Управление версиями службы данных (службы WCF Data Services).