管理数据服务上下文(WCF 数据服务)

DataServiceContext 类封装针对指定数据服务支持的操作。 尽管 OData 服务是无状态的,但上下文不是。 因此,可使用 DataServiceContext 类在数据服务的各个交互之间保持客户端的状态,以支持诸如更改管理之类的功能。 该类还对更改的标识和跟踪进行管理。

合并选项和标识解析

当执行 DataServiceQuery<TElement> 时,响应源中的实体将具体化为对象。 有关更多信息,请参见对象具体化(WCF 数据服务)。 将响应消息中的项具体化为对象所采用的方式将基于标识解析,并且依赖于执行查询时所依据的合并选项。 在单一 DataServiceContext 范围内执行多个查询或加载请求时,WCF 数据服务客户端将只跟踪具有特定键值的单个对象实例。 用于执行标识解析的此键唯一地标识一个实体。

默认情况下,客户端只针对 DataServiceContext 尚未跟踪的实体,将响应源中的项具体化为对象。 这意味着不会覆盖缓存中已存在的对象更改。 此行为通过为查询和加载操作指定 MergeOption 值进行控制。 通过设置 DataServiceContextMergeOption 属性可指定此选项。 默认的合并选项值为 AppendOnly。 这样将只为尚未进行跟踪的实体具体化对象,这意味着不会覆盖现有对象。 防止数据服务中的更新覆盖客户端上的对象更改的另一种方式是指定 PreserveChanges。 当指定 OverwriteChanges 时,客户端上对象的值将替换为响应源中对应项的最新值,即使已对这些对象进行了更改也是如此。 当使用 NoTracking 合并选项时,DataServiceContext 无法将对客户端对象所做的更改发送到数据服务。 使用此选项时,将始终用数据服务中的值覆盖更改。

管理并发

OData 支持使数据服务能够检测更新冲突的乐观并发。 可以按这种方式配置数据服务提供程序,使得数据服务能够使用并发标记检查实体是否更改。 此标记包含实体类型的一个或多个属性,数据服务通过验证这些属性来确定某个资源是否已更改。 并发标记包含在发送给数据服务的请求和从数据服务发出的响应的 eTag 标头中,由 WCF 数据服务客户端进行管理。有关更多信息,请参见更新数据服务(WCF 数据服务)

DataServiceContext 通过使用 AddObjectUpdateObjectDeleteObject 或通过 DataServiceCollection<T> 跟踪已手动报告的对对象所做的更改。 当调用 SaveChanges 方法时,客户端将更改发送回数据服务。 如果客户端中的数据更改与数据服务中的更改冲突,则 SaveChanges 会失败。 当发生这种情况时,您必须再次查询实体资源以接收更新数据。 若要覆盖数据服务中的更改,请使用 PreserveChanges 合并选项执行查询。 再次调用 SaveChanges 时,只要尚未对数据服务中的资源进行其他更改,客户端上保留的更改将永久保存到数据服务。

保存更改

DataServiceContext 实例中对更改进行跟踪,但不会将更改立即发送到服务器。 在完成对指定活动的所需更改后,调用 SaveChanges 以将所有更改提交给数据服务。 SaveChanges 操作完成后,会返回 DataServiceResponse 对象。 DataServiceResponse 对象包括一系列 OperationResponse 对象,这些对象依次又包含一系列表示已保留或尝试的更改的 EntityDescriptorLinkDescriptor 实例。 在数据服务中创建或修改实体之后,EntityDescriptor 包含对已更新实体的引用,其中包括所有服务器生成的属性值,例如上面示例中生成的 ProductID 值。 客户端库将使用这些新值自动更新 .NET Framework 对象。

对于成功的插入和更新操作,与操作关联的 EntityDescriptorLinkDescriptor 对象的状态属性设置为 Unchanged,并通过使用 OverwriteChanges 合并新值。

如果数据服务中的插入、更新或删除操作失败,则实体状态保持在调用 SaveChanges 之前的状态,并且 OperationResponseError 属性设置为包含有关该错误的信息的 DataServiceRequestException。 有关更多信息,请参见更新数据服务(WCF 数据服务)

管理请求

OData 协议为请求数据服务的行为和数据服务的响应行为提供了灵活性。 客户端库使您能够利用这种灵活性,方法是控制应用程序如何与数据服务进行交互。

设置更改操作的首选标头

默认情况下,只有在响应创建新实体的 POST 请求时才会返回消息负载。 在此情况下,新的实体返回在负载中。 这意味着当对象进行了更新,更新后的实体不返回在有效负载或响应消息中。 然而,OData 协议说明客户端可能会使用首选标头请求更改此默认行为。 在 POST、PUT、PATCH 或 MERGE 请求中,首选标头由 DataServiceContext 基于 DataServiceResponsePreference 的值(在 AddAndUpdateResponsePreference 属性中设置)生成。 下表显示首选标头选项和相关响应行为:

首选标头值

AddAndUpdateResponsePreference

响应行为

不包含在请求中。 这是默认行为。

None

响应负载只为 POST 请求返回,不为 PUT、PATCH 和 MERGE 请求返回。

return-content

IncludeContent

为所有更改请求返回响应负载。

return-no-content

NoContent

未为所有请求返回响应载荷。 对于 POST 请求,数据服务还在响应中包括 DServiceId 标头。 此标头用于交流新创建实体的键值。

备注

即使当数据服务支持某个支持首选标头的 OData 协议版本时,数据服务也可以选择不遵守这类请求处理首选项。

为更新设置 HTTP 方法

默认情况下,.NET Framework 客户端库将更新作为 MERGE 请求发送至现有实体。 在 OData 中,MERGE 请求将更新实体的选定属性;但客户端始终会在 MERGE 请求中包含所有属性,即使是未更改的属性也包含在内。 OData 协议还支持发送 PUT 和 PATCH 请求以更新实体。 在 PUT 请求中,现有实体实际上将替换为该实体的一个新实例,新实例具有来自客户端的属性值。 PATCH 请求的处理方式与 MERGE 请求相同;然而 PATCH 是标准 HTTP 操作,然而 MERGE 由 OData 定义。 这种更新行为可在调用 SaveChanges(SaveChangesOptions) 时,通过提供 ReplaceOnUpdate 值(以使用 PUT 请求)或 PatchOnUpdate 值(以使用 PATCH 请求)作为选项来指定。

备注

当客户端不知道实体的所有属性时,PUT 请求的行为会与 MERGE 请求或 PATCH 请求不同。当将某个实体类型投影到客户端上的新类型时,可能会发生这种情况。当新属性已经添加到服务数据模型中的实体中,同时 DataServiceContextIgnoreMissingProperties 属性设置为 true 以忽略这类客户端映射错误时,也会发生这种情况。在这种情况下,PUT 请求会将客户端未知的任何属性重置为默认值。

POST 隧道

默认情况下,客户端库通过使用 POST、GET、PUT/MERGE/PATCH 和 DELETE 等 HTTP 方法相应地向 OData 服务发送创建、读取、更新和删除请求。 这保持了代表状态传输 (REST) 的基本原则。 不过,不是每个 Web 服务器实现支持完整的 HTTP 方法集。 在某些情况下,受支持的方法可能会只限制为 GET 和 POST。 在中介(如防火墙)用某些方法阻止请求时,可能会发生这种情况。 因为 GET 和 POST 方法是支持最多的方法,所以 OData 指定了一种方法,通过使用 POST 请求执行任何不受支持的 HTTP方法。 这种方法称为方法隧道或 POST 隧道,使客户端能够发送 POST 请求,在自定义 X-HTTP-Method 标头中指定的实际方法。 要为请求启用 POST 隧道,将 DataServiceContext 实例上的 UsePostTunneling 属性设置为 true。

解析实体集的基 URI

默认情况下,客户端假定所有实体集,也称为集合,都共享相同的基 URI。 此基 URI 由 BaseUri 属性定义(在 DataServiceContext 中)。 然而,OData 协议允许数据服务公开实体集为具有不同基 URI 的源。 为了能够处理具有不同基 URI 的实体集,客户端允许您向 DataServiceContext 注册一个委托,该委托可用于解析各种实体集的基 URI。 此委托是一种采用字符串(实体集名称)并返回 Uri(指定的实体集的基 URI)的方法。 此解析程序通过向 ResolveEntitySet 属性赋值注册到 DataServiceContext。 当创建上下文时,示例解析程序实现可以阅读由数据服务根返回的集合信息,并在字典中存储每个集合的基 URI 值。 此字典随后可以由解析程序使用,以返回特定实体集的 URI 。 有关包括示例代码的更为完整的示例,请参阅文章实体集解析程序

版本控制要求

DataServiceContext 行为有以下 OData 协议版本要求:

  • 首选标头和 PATCH 请求的支持要求客户端和数据服务均支持 OData 协议的版本 3.0 以及更高版本。

  • 实体集解析程序的支持需要数据框架发行版中附带的 WCF 数据服务 客户端库或更高版本。

有关更多信息,请参见数据服务版本管理(WCF 数据服务)