Share via


ストリーミング プロバイダー (WCF Data Services)

データ サービスは、ラージ オブジェクトのバイナリ データを公開できます。このバイナリ データは、ビデオ ストリームとオーディオ ストリーム、画像、ドキュメント ファイル、またはその他の種類のバイナリのメディアを表すことができます。データ モデルのエンティティに 1 つ以上のバイナリ プロパティが含まれている場合、データ サービスは、このバイナリ データを応答フィードのエントリ内に Base-64 としてエンコードして返します。この方法で大きなバイナリ データを読み込んでシリアル化するとパフォーマンスに影響を及ぼす可能性があるため、Open Data Protocol (OData) では、属するエンティティとは独立してバイナリ データを取得するためのメカニズムが定義されています。これは、バイナリ データとエンティティを分離して 1 つ以上のデータ ストリームを生成することで実現されます。

  • メディア リソース - エンティティに属するバイナリ データ (ビデオ、オーディオ、画像、その他の種類のメディア リソース ストリームなど)。

  • メディア リンク エントリ - 関連するメディア リソース ストリームへの参照を含むエンティティ。

WCF Data Services では、ストリーミング データ プロバイダーを実装してバイナリ リソース ストリームを定義します。ストリーミング プロバイダーを実装すると、Stream オブジェクトとして特定のエンティティに関連付けられているメディア リソース ストリームがデータ サービスに提供されます。この実装によって、データ サービスでは、指定された MIME の種類のバイナリ データ ストリームとしてメディア リソースを HTTP 経由で受け入れて、返すことができます。

バイナリ データのストリーミングをサポートするデータ サービスを構成するには、次の手順に従う必要があります。

  1. データ モデル内の 1 つ以上のエンティティをメディア リンク エントリとして属性化します。これらのエンティティには、ストリーミング対象のバイナリ データを含めないでください。エンティティのバイナリ プロパティは、常に Base-64 でエンコードされたバイナリとしてエントリで返されます。

  2. T:System.Data.Services.Providers.IDataServiceStreamProvider インターフェイスを実装します。

  3. IServiceProvider インターフェイスを実装するデータ サービスを定義します。データ サービスは、GetService の実装を使用してストリーミング データ プロバイダーの実装にアクセスします。このメソッドは、適切なストリーミング プロバイダーの実装を返します。

  4. Web アプリケーション構成で大きいメッセージ ストリームを有効にします。

  5. サーバー上またはデータ ソース内のバイナリ リソースへのアクセスを有効にします。

このトピックの例はサンプルのストリーミング フォト サービスに基づいています。詳細については、ブログの記事「Data Services ストリーミング プロバイダー シリーズ: ストリーミング プロバイダーの実装 (パート 1)」を参照してください。このサンプル サービスのソース コードは、MSDN コード ギャラリーのストリーミング フォト データ サービスのサンプル ページで入手できます。

データ モデル内のメディア リンク エントリの定義

エンティティがデータ モデル内のメディア リンク エントリとして定義される方法は、データ ソース プロバイダーによって決定されます。

  • Entity Framework プロバイダー
    エンティティがメディア リンク エントリであることを示すには、概念モデルのエンティティ型定義に HasStream 属性を追加します。次にその例を示します。

    <EntityType xmlns:m="https://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
                Name="PhotoInfo" m:HasStream="true">
      <Key>
        <PropertyRef Name="PhotoId" />
      </Key>
      <Property Name="PhotoId" Type="Int32" Nullable="false" 
                annotation:StoreGeneratedPattern="Identity" />
      <Property Name="FileName" Type="String" Nullable="false" />
      <Property Name="FileSize" Type="Int32" Nullable="true" />
      <Property Name="DateTaken" Type="DateTime" Nullable="true" />
      <Property Name="TakenBy" Type="String" Nullable="true" />
      <Property Name="DateAdded" Type="DateTime" Nullable="false" />
      <Property Name="Exposure" Type="PhotoData.Exposure" Nullable="false" />
      <Property Name="Dimensions" Type="PhotoData.Dimensions" Nullable="false" />
      <Property Name="DateModified" Type="DateTime" Nullable="false" />
      <Property Name="Comments" Type="String" MaxLength="Max" 
                FixedLength="false" Unicode="true" />
      <Property Name="ContentType" Type="String" MaxLength="50" FixedLength="false" Unicode="true" />
    </EntityType>
    

    また、エンティティまたはデータ モデルを定義する .edmx ファイルまたは .csdl ファイルのルートに名前空間 xmlns:m=https://schemas.microsoft.com/ado/2007/08/dataservices/metadata を追加する必要があります。

    Entity Framework プロバイダーを使用してメディア リソースを公開するデータ サービス の例については、ブログの記事「Data Services ストリーミング プロバイダー シリーズ: ストリーミング プロバイダーの実装 (パート 1)」を参照してください。

  • リフレクション プロバイダー
    エンティティがメディア リンク エントリであることを示すには、リフレクション プロバイダーのエンティティ型を定義するクラスに HasStreamAttribute を追加します。

IDataServiceStreamProvider インターフェイスの実装

バイナリ データ ストリームをサポートするデータ サービスを作成するには、IDataServiceStreamProvider インターフェイスを実装する必要があります。これを実装すると、データ サービスはバイナリ データをストリームとしてクライアントに返し、クライアントから送信されたストリームとしてバイナリ データを使用できます。データ サービスでは、バイナリ データへのストリームとしてのアクセスが必要になるたびに、このインターフェイスのインスタンスを作成します。IDataServiceStreamProvider インターフェイスでは次のメンバーを指定します。

メンバー名 説明

DeleteStream

このメソッドはデータ サービスにより呼び出され、メディア リンク エントリが削除されたときに対応するメディア リソースを削除します。IDataServiceStreamProvider を実装する場合、このメソッドには、指定されたメディア リンク エントリに関連付けられたメディア リソースを削除するコードが含まれます。

GetReadStream

このメソッドはデータ サービスにより呼び出され、メディア リソースをストリームとして返します。IDataServiceStreamProvider を実装する場合、このメソッドには、指定されたメディア リンク エントリに関連付けられたメディア リソースを返すためにデータ サービスが使用するストリームを提供するコードが含まれます。

GetReadStreamUri

このメソッドはデータ サービスにより呼び出され、メディア リンク エントリのメディア リソースを要求するために使用される URI を返します。この値を使用して、メディア リンク エントリのコンテンツ要素の src 属性が作成され、データ ストリームが要求されます。このメソッドから null が返されると、データ サービスによって URI が自動的に決定されます。このメソッドは、ストリーミング プロバイダーを使用しないバイナリ データへの直接アクセスをクライアントに提供する必要がある場合に使用します。

GetStreamContentType

このメソッドはデータ サービスにより呼び出され、指定されたメディア リンク エントリに関連付けられたメディア リソースの Content-Type 値を返します。

GetStreamETag

このメソッドはデータ サービスにより呼び出され、指定されたエンティティに関連付けられたデータ ストリームの eTag を返します。このメソッドは、バイナリ データの同時実行を管理する場合に使用されます。このメソッドが null を返す場合、データ サービスでは同時実行が追跡されません。

GetWriteStream

このメソッドはデータ サービスにより呼び出され、クライアントから送信されたストリームの受信時に使用されるストリームを取得します。IDataServiceStreamProvider を実装する場合、データ サービスが受信したストリーム データを書き込む先である書き込み可能なストリームを返す必要があります。

ResolveType

名前空間で修飾された型名を返します。この型は、挿入されるメディア リソースのデータ ストリームに関連付けられたメディア リンク エントリに対してデータ サービス ランタイムが作成する必要がある型を表します。

ストリーミング データ サービスの作成

WCF Data Services ランタイムに IDataServiceStreamProvider の実装へのアクセスを提供するには、作成するデータ サービスで IServiceProvider インターフェイスも実装する必要があります。次の例は、GetService メソッドを実装して、IDataServiceStreamProvider を実装する PhotoServiceStreamProvider クラスのインスタンスを返す方法を示しています。

Partial Public Class PhotoData
    Inherits DataService(Of PhotoDataContainer)
    Implements IServiceProvider

    ' This method is called only once to initialize service-wide policies.
    Public Shared Sub InitializeService(ByVal config As DataServiceConfiguration)
        config.SetEntitySetAccessRule("PhotoInfo", _
            EntitySetRights.ReadMultiple Or _
            EntitySetRights.ReadSingle Or _
            EntitySetRights.AllWrite)

        ' Named streams require version 3 of the OData protocol.
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3
    End Sub
#Region "IServiceProvider Members"
    Public Function GetService(ByVal serviceType As Type) As Object _
    Implements IServiceProvider.GetService
        If serviceType Is GetType(IDataServiceStreamProvider) _
            Or serviceType Is GetType(IDataServiceStreamProvider2) Then
            Return New PhotoServiceStreamProvider(Me.CurrentDataSource)
        End If
        Return Nothing
    End Function
#End Region
End Class
public partial class PhotoData : DataService<PhotoDataContainer>, IServiceProvider
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("PhotoInfo",
            EntitySetRights.ReadMultiple |
            EntitySetRights.ReadSingle |
            EntitySetRights.AllWrite);

        // Named resource streams require version 3 of the OData protocol.
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
    }
    public object GetService(Type serviceType)
    {
        if (serviceType == typeof(IDataServiceStreamProvider2))
        {
            // Return the stream provider to the data service.
            return new PhotoServiceStreamProvider(this.CurrentDataSource);
        }
        
        return null;
    }
}

データ サービスの作成方法に関する一般的な情報については、「データ サービスの構成 (WCF Data Services)」を参照してください。

ホスト環境での大きなバイナリ ストリームの有効化

ASP.NET Web アプリケーションのデータ サービスを作成する場合、Windows Communication Foundation (WCF) を使用して HTTP プロトコルが実装されます。既定では、WCF では HTTP メッセージのサイズは 65K バイトのみに制限されます。また、データ サービスに対する大きなバイナリ データのストリーミングを可能にするには、大きなバイナリ ファイルを有効にして、転送にストリームを使用するように Web アプリケーションを構成する必要もあります。そのためには、アプリケーションの Web.config ファイルの <configuration /> 要素に次の内容を追加します。

 <system.serviceModel>
     <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
     <services>
         <!-- The name of the service -->
         <service name="PhotoService.PhotoData">
             <!--you can leave the address blank or specify your end point URI-->
             <endpoint binding="webHttpBinding" bindingConfiguration="higherMessageSize" 
               contract="System.Data.Services.IRequestHandler"></endpoint>
         </service>
     </services>
     <bindings>
         <webHttpBinding>
             <!-- configure the maxReceivedMessageSize value to suit the max size of 
the request (in bytes) you want the service to receive-->
             <binding name="higherMessageSize" transferMode="Streamed"  
              maxReceivedMessageSize="2147483647"/>
         </webHttpBinding>
     </bindings>
 </system.serviceModel>
Ee960144.note(ja-jp,VS.100).gif注 :
System.ServiceModel.TransferMode.Streamed 転送モードを使用して、要求メッセージと応答メッセージの両方のバイナリ データをストリーミングし、WCF によってバッファリングされないようにする必要があります。

詳細については、「Streaming Message Transfer」および「Transport Quotas」を参照してください。

また、既定では、インターネット インフォメーション サービス (IIS) でも要求のサイズが 4 MB に制限されます。IIS 上で実行時にデータ サービスが 4 MB を超えるストリームを受信できるようにするには、次の例に示すように、<system.web /> 構成セクション内の httpRuntime ElementmaxRequestLength 属性を設定する必要があります。

  <system.web>
      <!-- maxRequestLength (in KB): default=4000 (4MB); max size=2048MB. -->
      <httpRuntime maxRequestLength="2000000"/>
</system.web>

クライアント アプリケーションでのデータ ストリームの使用

WCF Data Services クライアント ライブラリを使用すると、クライアントのバイナリ ストリームとして公開されたリソースを取得および更新できます。詳細については、「バイナリ データの操作 (WCF Data Services)」を参照してください。

ストリーミング プロバイダーの使用に関する考慮事項

ストリーミング プロバイダーを実装する場合およびデータ サービスからメディア リソースにアクセスする場合には、次の点を考慮してください。

  • MERGE 要求は、メディア リソースではサポートされません。既存のエンティティのメディア リソースを変更するには、PUT 要求を使用します。

  • POST 要求を使用して新しいメディア リンク エントリを作成することはできません。代わりに、POST 要求を発行して新しいメディア リソースを作成する必要があります。データ サービスによって、既定値で新しいメディア リンク エントリが作成されます。その後に MERGE 要求または PUT 要求を使用してこの新しいエンティティを更新できます。プロパティ値を POST 要求の Slug ヘッダーの値に設定するなど、エンティティをキャッシュしてディスポーザーで更新を行うこともできます。

  • POST 要求を受信すると、データ サービスは GetWriteStream を呼び出してメディア リソースを作成してから、SaveChanges を呼び出してメディア リンク エントリを作成します。

  • GetWriteStream を実装すると、MemoryStream オブジェクトは返されません。この種類のストリームを使用すると、サービスが非常に大きなデータ ストリームを受信した場合に、メモリ リソースの問題が発生します。

  • データベースにメディア リソースを格納する場合は、次の点を考慮してください。

    • メディア リソースであるバイナリ プロパティをデータ モデルに含めないようにしてください。データ モデルで公開されるプロパティはすべて、応答フィードのエントリで返されます。

    • 大きなバイナリ ストリームのパフォーマンスを向上させるには、カスタム ストリーム クラスを作成してバイナリ データをデータベースに格納することをお勧めします。このクラスは、GetWriteStream の実装によって返され、バイナリ データをチャンク単位でデータベースに送信します。SQL Server データベースでは、バイナリ データが 1 MB を超える場合、FILESTREAM を使用してデータをデータベースにストリーミングすることをお勧めします。

    • データ サービスによって受信される大きなバイナリ ストリームを格納できるようにデータベースが設計されていることを確認してください。

    • クライアントが POST 要求を送信して、1 回の要求でメディア リソースと共にメディア リンク エントリを挿入する場合は、データ サービスによって新しいエンティティがデータベースに挿入される前に、GetWriteStream を呼び出してストリームを取得します。ストリーミング プロバイダーは、このデータ サービスの動作を処理できるように実装する必要があります。エンティティがデータベースに挿入されるまで、個別のデータ テーブルを使用してバイナリ データを格納するか、データ ストリームをファイルに格納することを検討してください。

  • DeleteStream メソッド、GetReadStream メソッド、または GetWriteStream メソッドを実装する場合は、メソッドのパラメーターとして指定される eTag 値および Content-Type 値を使用する必要があります。IDataServiceStreamProvider プロバイダーの実装には、eTag ヘッダーまたは Content-Type ヘッダーを設定しないでください。

  • 既定では、クライアントはチャンクされた HTTP Transfer-Encoding を使用して、大きなバイナリ ストリームを送信します。ASP.NET 開発サーバーはこの種類のエンコーディングをサポートしていないので、この Web サーバーを使用して大きなバイナリ ストリームを受け取る必要があるストリーミング データ サービスをホストすることはできません。ASP.NET 開発サーバーの詳細については、「Web Servers in Visual Web Developer」を参照してください。

バージョン管理の要件

ストリーミング プロバイダーには、次に示す OData プロトコルのバージョン管理の要件があります。

  • ストリーミング プロバイダーを使用するには、データ サービスでバージョン 2.0 以降の OData プロトコルがサポートされている必要があります。

詳細については、「WCF Data Services の複数のバージョンの使用」を参照してください。

参照

概念

データ サービス プロバイダー (WCF Data Services)
カスタム データ サービス プロバイダー (WCF Data Services)
バイナリ データの操作 (WCF Data Services)