使用二进制数据(WCF 数据服务)
利用 WCF 数据服务客户端库,您可以通过以下方式之一从 开放式数据协议 (OData) 源中检索二进制数据并进行更新。
作为实体的基元类型属性。 当使用可轻松加载到内存中的小型二进制数据对象时,建议使用此方法。 在这种情况下,二进制属性是数据模型公开的实体属性,而数据服务会在响应消息中将二进制数据序列化为 base-64 二进制编码的 XML。
作为单独的二进制资源流。 当访问和更改可能表示照片、视频或其他任何类型的二进制编码数据的二进制大型对象 (BLOB) 数据时,建议使用此方法。
WCF 数据服务通过使用 HTTP 实现二进制数据流,如 OData 协议中定义。 OData提供了以下的流媒体机制将二进制数据与某个实体关联:
媒体资源/媒体链接项
Atom 发布协议 (AtomPub) 定义了一种机制,将二进制数据作为媒体资源与数据源中的条目关联,该条目称为媒体链接项。 只能有一个媒体资源为给定的媒体链接条目定义。 媒体资源可以被视为一个实体的默认流。 OData从 AtomPub 继承此流的行为。
命名资源流
从 OData 版本 3 开始,一个实体可以有多个相关的资源流,其可以按名称访问流。 这种机制不依赖 AtomPub,所以已命名资源流可用并且不是媒体链接条目。 媒体链接条目也可有命名流。 有关更多信息,请参见流提供程序(WCF 数据服务)。
实体元数据
有相关的二进制资源流的实以数据服务元数据中表示,用以下的方式,取决于流的类型之一:
媒体资源:
按 HasStream 属性,实体类型是媒体链接条目。
命名资源流:
按数据模型中实体的一个或多个属性,其属于 Stream 数据类型。
支持数据模型中的 Stream 数据类型需要版本 2.2 的 EDM。 有关更多信息,请参见Streaming Provider (WCF Data Services)。
在下面的示例中,PhotoInfo 实体是媒体链接入口,它具有一个由 HasStream 属性表示的相关媒体资源,以及命名资源流,名称为 Thumbnail。
<EntityType Name="PhotoInfo" m:HasStream="true">
<Key>
<PropertyRef Name="PhotoId" />
</Key>
<Property Name="PhotoId" Type="Edm.Int32" Nullable="false"
p9:StoreGeneratedPattern="Identity"
xmlns:p9="https://schemas.microsoft.com/ado/2009/02/edm/annotation" />
<Property Name="FileName" Type="Edm.String" Nullable="false" />
<Property Name="FileSize" Type="Edm.Int32" Nullable="true" />
<Property Name="DateTaken" Type="Edm.DateTime" Nullable="true" />
<Property Name="TakenBy" Type="Edm.String" Nullable="true" />
<Property Name="DateAdded" Type="Edm.DateTime" Nullable="false" />
<Property Name="Exposure" Type="PhotoData.Exposure" Nullable="false" />
<Property Name="Dimensions" Type="PhotoData.Dimensions" Nullable="false" />
<Property Name="DateModified" Type="Edm.DateTime" Nullable="false" />
<Property Name="Comments" Type="Edm.String" Nullable="true" MaxLength="Max"
Unicode="true" FixedLength="false" />
<Property Name="ContentType" Type="Edm.String" Nullable="true" MaxLength="50"
Unicode="true" FixedLength="false" />
<Property Name="Thumbnail" Type="Edm.Stream" Nullable="false" />
</EntityType>
本主题中的其余示例揭示了如何访问和更改媒体资源流。 有关如何通过使用 WCF 数据服务客户端库在 .NET Framework 客户端应用程序中使用媒体资源的完整示例,请参见从客户端访问媒体资源流一文。
访问二进制资源流
WCF 数据服务客户端库提供了从基于 OData 的数据服务访问二进制资源流的方法。 下载媒体资源时,可以使用媒体资源的 URI,也可以获取一个包含媒体资源数据本身的二进制流。 还可以上载媒体资源数据作为一个二进制流。
提示
有关如何创建一个 Windows Presentation Foundation (WPF) 客户端应用程序(它从存储照片的 OData 服务下载二进制图像文件)的逐步示例,请参见数据服务流提供程序系列文章 - 第 2 部分:从客户端访问媒体资源流一文。要下载博客文章中的流照片数据服务的示例代码,请参见 MSDN 代码库中的流照片数据服务示例。
获取二进制流的 URI
检索某些类型的媒体资源(如图像和其他媒体文件)时,在应用程序中使用媒体资源的 URI 通常比处理二进制数据流本身更容易。 要获取与给定媒体链接入口相关联的资源流的 URI,必须对跟踪实体的 DataServiceContext 实例调用 GetReadStreamUri(Object) 方法。 要获取已命名的资源流的 URI,调用方法重载,其采用 name 参数,它是流的名称。 下面的示例揭示了如何调用 GetReadStreamUri(Object) 方法以获取用于在客户端上创建新图像的媒体资源流的 URI:
' Use the ReadStreamUri of the Media Resource for selected PhotoInfo object
' as the URI source of a new bitmap image.
photoImage.Source = New BitmapImage(context.GetReadStreamUri(currentPhoto))
// Use the ReadStreamUri of the Media Resource for selected PhotoInfo object
// as the URI source of a new bitmap image.
photoImage.Source = new BitmapImage(context.GetReadStreamUri(currentPhoto));
对于命名的资源流,也可以直接从流属性中获得流的 URI。 对于数据服务返回的媒体链接条目的每个属性(其为 Stream 类型),在数据服务工具生成返回 DataServiceStreamLink 实例的属性。 Uri 属性(属于此 DataServiceStreamLink)是命名的资源流的 URI。 这使您可以获取 URI,并直接从媒体链接条目对象获取,或作为语言集成查询 (LINQ) 的结果获取。
下载二进制资源流
检索二进制资源流时,必须对跟踪媒体链接入口的 DataServiceContext 实例调用 GetReadStream 方法。 该方法向数据服务发送一个返回 DataServiceStreamResponse 对象的请求,该对象具有对包含资源的流的引用。 当应用程序要求将二进制资源作为 Stream 时可使用该方法。 要获取已命名的资源流,调用方法重载,其采用 name 参数,它是资源流的名称。 下面的示例揭示了如何调用 GetReadStream 方法以检索用于在客户端上创建新图像的流:
' Get the read stream for the Media Resource of the currently selected
' entity (Media Link Entry).
Using response As DataServiceStreamResponse = _
context.GetReadStream(currentEmployee, "image/bmp")
' Use the returned binary stream to create a bitmap image that is
' the source of the image control.
employeeImage.Source = CreateBitmapFromStream(response.Stream)
End Using
// Get the read stream for the Media Resource of the currently selected
// entity (Media Link Entry).
using (DataServiceStreamResponse response =
context.GetReadStream(currentEmployee, "image/bmp"))
{
// Use the returned binary stream to create a bitmap image that is
// the source of the image control.
employeeImage.Source = CreateBitmapFromStream(response.Stream);
}
备注
数据服务不会设置包含二进制数据流的响应消息中的 Content-Length 标头。此值可能不反映二进制数据流的实际长度。
将媒体资源作为流上载
若要插入或更新媒体资源,请对正在跟踪实体的 DataServiceContext 实例调用 SetSaveStream 方法。 此方法向包含从所提供的流中读取的媒体资源的数据服务发送请求。 要上传已命名的资源流的 URI,调用方法重载,其采用 name 参数,它是资源流的名称。 下面的示例演示如何调用 SetSaveStream 方法,以便将属于特定员工的位图图像发送给数据服务:
' Set the file stream as the source of binary stream
' to send to the data service. The Slug header is the file name and
' the content type is determined from the file extension.
' A value of 'true' means that the stream is closed by the client when
' the upload is complete.
context.SetSaveStream(photoEntity, imageStream, True, _
photoEntity.ContentType, photoEntity.FileName)
// Set the file stream as the source of binary stream
// to send to the data service. The Slug header is the file name and
// the content type is determined from the file extension.
// A value of 'true' means that the stream is closed by the client when
// the upload is complete.
context.SetSaveStream(photoEntity, imageStream, true,
photoEntity.ContentType, photoEntity.FileName);
在此示例中,通过为 closeStream 参数提供 true 值,调用 SetSaveStream 方法。 这样可保证在将二进制数据上载到数据服务之后,DataServiceContext 将会关闭流。
备注
调用 SetSaveStream(Object, String, Stream, Boolean, String) 时,只有在调用 SaveChanges 之后,才会将流发送到数据服务。