Condividi tramite


Provider di flusso (WCF Data Services)

Un servizio dati può esporre dati Large Object Binary. Tali dati binari possono rappresentare flussi audio e video, immagini, file documento o altri tipi di elementi multimediali binari. Quando un'entità del modello di dati include una o più proprietà binarie, il servizio dati restituisce tali dati binari codificati in base 64 all'interno dell'elemento entry presente nel feed di risposta. Poiché questo tipo di caricamento e serializzazione di dati binari di grandi dimensioni può influire sulle prestazioni, il OData (Open Data Protocol) definisce un meccanismo per recuperare i dati binari indipendentemente dall'entità alla quale appartengono. Questa operazione viene eseguita separando i dati binari dall'entità in uno o più flussi di dati.

Il protocollo OData supporta i due meccanismi seguenti per esporre i dati binari come flussi correlati a un'entità:

  • Risorsa multimediale/voce di collegamento multimediale

    Il protocollo di pubblicazione Atom (AtomPub) definisce un meccanismo per associare i dati binari come una risorsa multimediale a una voce in un feed di dati, definita voce di collegamento multimediale. Può essere presente solo una risorsa multimediale definita per una voce di collegamento multimediale specificata. Una risorsa multimediale può essere considerata come il flusso predefinito per un'entità. OData eredita questo comportamento di flusso da AtomPub.

  • Flusso di risorse denominato

    A partire dalla versione 3 di OData un'entità può contenere più flussi di risorse correlati, a cui è possibile accedervi in base al nome. Questo meccanismo non dipende da AtomPub, pertanto è possibile che un'entità contenga flussi di risorse denominati ma non sia una voce di collegamento multimediale. È inoltre possibile che una voce di collegamento multimediale contenga flussi denominati. Per ulteriori informazioni, vedere il post Flussi di risorse denominati.

Con WCF Data Services è possibile definire i flussi di risorse binari implementando i provider di dati di flusso. Le implementazioni dei provider di flusso forniscono al servizio dati i flussi associati a un'entità specifica come gli oggetti Stream.

La configurazione di un servizio dati per supportare il flusso di dati binari richiede l'esecuzione dei passaggi seguenti:

  1. Attribuire l'entità nel modello di dati che contiene i flussi di risorse correlati. Ogni provider di dati dispone di propri requisiti e ogni tipo di flusso di risorse binario viene definito nel modello di dati da un meccanismo diverso.

  2. Implementare le interfacce del provider di flusso seguenti:

  3. Definire un servizio dati che implementi l'interfaccia IServiceProvider. Il servizio dati utilizza l'implementazione GetService per accedere all'implementazione del provider di dati di flusso. Questo metodo restituisce l'implementazione del provider di flusso appropriata.

  4. Abilitare flussi di messaggi di grandi dimensioni nella configurazione dell'applicazione Web.

  5. Abilitare accesso alle risorse binarie sul server o in un'origine dati.

Gli esempi in questo argomento sono basati su un servizio di foto di flusso di esempio, discusso in dettaglio nel post Serie provider di flusso di Data Services: Implementazione di un provider di flusso (parte 1). Il codice sorgente per questo servizio di esempio è disponibile nella pagina Esempio di servizio dati foto di flusso su MSDN Code Gallery.

Definizione dei flussi di risorse nel modello di dati

Il modo in cui un flusso di risorse binario viene definito nel modello di dati varia a seconda se il flusso è una risorsa multimediale o un flusso di risorse denominato, nonché dipende dal provider dell'origine dati utilizzato. Nell'esempio seguente viene illustrata la definizione di una risorsa multimediale nei metadati restituiti dal servizio dati, dove PhotoInfo è una voce di collegamento multimediale che contiene anche un flusso di risorse denominato (Thumbnail) definito:

<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>

Provider di Entity Framework

Quando si utilizza il provider di Entity Framework, è possibile definire un flusso di risorse binario nel modello di dati stesso in uno dei modi seguenti, a seconda del tipo di flusso:

  • Flusso di risorse multimediali:

    Per indicare che un'entità è una voce di collegamento multimediale contenente una risorsa multimediale associata, aggiungere l'attributo HasStream alla definizione del tipo di entità nel modello concettuale. È inoltre necessario aggiungere un riferimento allo spazio dei nomi xmlns:m=https://schemas.microsoft.com/ado/2007/08/dataservices/metadata alla voce di collegamento multimediale o a uno degli elementi padre nel modello di dati.

  • Flusso di risorse denominato:

    Un flusso denominato che appartiene a una voce di collegamento multimediale viene definito come una proprietà di tipo Stream nel modello concettuale.

    Importante

    A partire dalla versione 2.2 il tipo di dati Stream è supportato da Entity Data Model (EDM).Tuttavia, in .NET Framework 4 Entity Framework non supporta questa versione di EDM.Come soluzione alternativa, è possibile definire invece un flusso di risorse denominato nel modello di dati applicando NamedStreamAttribute alla classe nel livello oggetti del modello di dati che rappresenta l'entità.In questo attributo il parametro name rappresenta il nome del flusso.È consigliabile aggiungere questo attributo alla classe di entità creando una definizione di classe parziale gestita in un file di codice separato. In caso contrario, questa personalizzazione verrà sovrascritta quando le classi di dati di entità vengono rigenerate da Entity Framework.Analogamente al provider di reflection, il servizio dati genera una proprietà del parametro name fornito di tipo Stream nel modello di dati.

Per un esempio ll'esposizione di una risorsa multimediale mediante il provider Entity Framework, vedere il post Serie provider di flusso di Data Services: Implementazione di un provider di flusso (parte 1).

Provider di reflection

Quando si utilizza il provider di reflection, è possibile identificare che un flusso di risorse binario appartiene a un tipo di entità applicando gli attributi in uno dei modi seguenti alla classe che rappresenta il tipo di entità, a seconda del tipo di flusso:

  • Flusso di risorse multimediali:

    Applicare HasStreamAttribute per definire un flusso di risorse multimediali (predefinito) che appartiene al tipo, che è una voce di collegamento multimediale.

  • Flusso di risorse denominato:

    Applicare NamedStreamAttribute per definire un flusso di risorse denominato che appartiene al tipo di entità, dove il parametro name fornito rappresenta il nome del flusso.

Provider di servizi dati personalizzati

Quando si utilizzano provider di servizi personalizzati, si implementa l'interfaccia IDataServiceMetadataProvider per definire i metadati per il servizio dati. Per ulteriori informazioni, vedere Provider di servizi dati personalizzati (WCF Data Services). È possibile indicare che un flusso di risorse binario appartiene a un oggetto ResourceType in uno dei modi seguenti:

Implementazione delle interfacce del provider di flusso

Per creare un servizio dati che supporta i flussi di dati binari, è necessario implementare almeno l'interfaccia IDataServiceStreamProvider. Questa implementazione consente al servizio dati di restituire al client i dati binari sotto forma di flusso e di utilizzarli come flusso inviato dal client. Per supportare i flussi denominati, è inoltre necessario implementare l'interfaccia IDataServiceStreamProvider2. Il servizio dati crea un'istanza dell'interfaccia appropriata ogni volta che deve accedere ai dati binari sotto forma di flusso.

IDataServiceStreamProvider

L'interfaccia IDataServiceStreamProvider specifica i membri seguenti:

Nome membro

Descrizione

DeleteStream

Questo metodo viene richiamato dal servizio dati per eliminare la risorsa multimediale corrispondente e tutti i flussi denominati quando viene eliminata la relativa voce di collegamento multimediale. Quando si implementa IDataServiceStreamProvider, questo metodo contiene il codice che elimina tutti i flussi di dati binari associati alla voce di collegamento multimediale fornita.

GetReadStream

Questo metodo viene richiamato dal servizio dati per restituire una risorsa multimediale come flusso. Quando si implementa IDataServiceStreamProvider, questo metodo contiene il codice che fornisce un flusso utilizzato dal servizio dati per restituire la risorsa multimediale associata all'elemento entry di collegamento multimediale specifico.

GetReadStreamUri

Questo metodo viene richiamato dal servizio dati per restituire l'URI utilizzato per richiedere la risorsa multimediale relativa all'elemento entry di collegamento multimediale. Questo valore consente di creare l'attributo src nell'elemento di contenuto dell'entry di collegamento multimediale che viene utilizzato per richiedere il flusso di dati. Quando questo metodo restituisce null, il servizio dati determina automaticamente l'URI. Utilizzare questo metodo quando è necessario fornire ai client accesso diretto ai dati binari senza utilizzare il provider di flusso.

GetStreamContentType

Questo metodo viene richiamato dal servizio dati per restituire il valore Content-Type della risorsa multimediale associata all'elemento entry di collegamento multimediale specificato.

GetStreamETag

Questo metodo viene richiamato dal servizio dati per restituire il valore eTag del flusso di dati associato all'entità specificata e viene utilizzato per gestire la concorrenza dei dati binari. Quando questo metodo restituisce null , il servizio dati non rileva la concorrenza.

GetWriteStream

Questo metodo viene richiamato dal servizio dati per ottenere il flusso utilizzato per la ricezione del flusso inviato dal client. Quando si implementa IDataServiceStreamProvider, è necessario restituire un flusso scrivibile nel quale il servizio dati possa scrivere i dati del flusso ricevuti.

ResolveType

Restituisce un nome di tipo completo con lo spazio dei nomi che rappresenta il tipo che il runtime del servizio dati deve creare per l'elemento entry di collegamento multimediale associato al flusso di dati della risorsa multimediale inserita.

IDataServiceStreamProvider2

L'interfaccia IDataServiceStreamProvider2 specifica i membri seguenti che eseguono l'overload dei membri di IDataServiceStreamProvider per accettare un parametro ResourceProperty che è un flusso di risorse denominate:

Nome membro

Descrizione

GetReadStream(Object, ResourceProperty, String, Nullable<Boolean>, DataServiceOperationContext)

Questo metodo viene richiamato dal servizio dati per restituire un flusso denominato. Quando si implementa IDataServiceStreamProvider2, questo metodo contiene il codice che fornisce un flusso utilizzato dal servizio dati per restituire la il flusso denominato richiesto associato alla voce di collegamento multimediale fornita.

GetReadStreamUri(Object, ResourceProperty, DataServiceOperationContext)

Questo metodo viene richiamato dal servizio dati per restituire l'URI utilizzato per richiedere un flusso denominato specifico per la voce di collegamento multimediale. Questo valore viene utilizzato per creare l'elemento atom:link utilizzato per richiedere il flusso denominato. Quando questo metodo restituisce null, il servizio dati determina automaticamente l'URI. Utilizzare questo metodo quando è necessario fornire ai client accesso diretto ai dati binari senza utilizzare il provider di flusso.

GetStreamContentType(Object, ResourceProperty, DataServiceOperationContext)

Questo metodo viene richiamato dal servizio dati per restituire il valore Content-Type di un flusso denominato specifico associato alla voce di collegamento multimediale specificata.

GetStreamETag(Object, ResourceProperty, DataServiceOperationContext)

Questo metodo viene richiamato dal servizio dati per restituire il valore eTag del flusso denominato specifico associato all'entità specificata e viene utilizzato per gestire la concorrenza dei dati binari. Quando questo metodo restituisce null , il servizio dati non rileva la concorrenza.

GetWriteStream(Object, ResourceProperty, String, Nullable<Boolean>, DataServiceOperationContext)

Questo metodo viene richiamato dal servizio dati per ottenere il flusso utilizzato per la ricezione di un flusso denominato inviato dal client. Quando si implementa IDataServiceStreamProvider2, è necessario restituire un flusso scrivibile nel quale il servizio dati possa scrivere i dati del flusso ricevuti.

Creazione del servizio dati di flusso

Per fornire al runtime di WCF Data Services l'accesso alle implementazioni di IDataServiceStreamProvider e IDataServiceStreamProvider2, il servizio dati creato deve implementare anche l'interfaccia IServiceProvider. Nell'esempio seguente viene illustrato come implementare il metodo GetService per restituire un'istanza della classe PhotoServiceStreamProvider che implementa IDataServiceStreamProvider e IDataServiceStreamProvider2.

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;
    }
}

Per informazioni generali sulla creazione di un servizio dati, vedere Configurazione del servizio dati (WCF Data Services).

Abilitazione dei flussi binari di grandi dimensioni nell'ambiente di hosting

Quando si crea un servizio dati in un'applicazione Web di ASP.NET, Windows Communication Foundation (WCF) viene utilizzato per fornire l'implementazione del protocollo HTTP. Per impostazione predefinita, WCF limita la dimensione dei messaggi HTTP a soli 65 KB. Per consentire il flusso dei dati binari di grandi dimensioni verso e dal servizio dati, è inoltre necessario configurare l'applicazione Web per l'abilitazione di file binari di grandi dimensioni e l'utilizzo di flussi per il trasferimento. A tal fine, aggiungere quanto segue all'elemento <configuration /> del file Web.config dell'applicazione:

   <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>

Nota

È necessario utilizzare una modalità di trasferimento del campo TransferMode.Streamed per assicurarsi che i dati binari nei messaggi di richiesta e di risposta vengano trasmessi, ma non memorizzati nel buffer da parte di WCF.

Per ulteriori informazioni, vedere Streaming Message Transfer e Transport Quotas.

Per impostazione predefinita, Internet Information Services (IIS) consente anche di limitare la dimensione delle richieste a 4 MB. Per permettere al servizio dati di ricevere flussi superiori a 4 MB quando viene eseguito in IIS, è necessario impostare anche l'attributo maxRequestLength dell'elemento httpRuntime Element nella sezione di configurazione <system.web />, come mostrato nell'esempio seguente:

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

Utilizzo dei flussi di dati in un'applicazione client

È possibile accedere direttamente a un flusso di dati binari tramite uno degli URI seguenti:

  • Flusso di risorse multimediali:

    https://localhost/PhotoService/PhotoData.svc/PhotoInfo(1)/$value
    
  • Flusso di risorse denominato:

    https://localhost/PhotoService/PhotoData.svc/PhotoInfo(1)/Thumbnail
    

La libreria client WCF Data Services consente di recuperare e aggiornare tali risorse esposte come flussi binari sul client. Per ulteriori informazioni, vedere Utilizzo di dati binari (WCF Data Services).

Considerazioni sull'utilizzo di un provider di flusso

Quando si implementa un provider di flusso e si accede alle risorse multimediali da un servizio dati, è necessario tenere presente le considerazioni seguenti.

  • È necessario implementare l'interfaccia IDataServiceStreamProvider per supportare i flussi di risorse multimediali o i flussi di risorse denominati. Per supportare i flussi di risorse denominati, è inoltre necessario implementare l'interfaccia IDataServiceStreamProvider2.

  • Quando si definisce un flusso di risorsa denominato che appartiene a una voce di collegamento multimediale, l'entità definita nel modello di dati non deve includere una proprietà con lo stesso nome del flusso.

  • Le richieste MERGE non sono supportate per le risorse multimediali. Utilizzare una richiesta PUT per modificare la risorsa multimediale di un'entità esistente.

  • Non è possibile utilizzare una richiesta POST per creare un nuovo elemento entry di collegamento multimediale. È invece necessario inviare una richiesta POST per creare una nuova risorsa multimediale. Il servizio dati crea un nuovo elemento entry di collegamento multimediale con i valori predefiniti. Questa nuova entità può essere aggiornata da una richiesta MERGE o PUT successiva. È anche possibile memorizzare l'entità nella cache ed eseguire nell'elemento di eliminazione aggiornamenti, quale l'impostazione del valore della proprietà sul valore dell'intestazione Slug nella richiesta POST.

  • Quando viene ricevuta una richiesta POST, il servizio dati chiama GetWriteStream per creare la risorsa multimediale prima di chiamare SaveChanges per creare l'elemento entry di collegamento multimediale.

  • Un'implementazione di GetWriteStream non deve restituire un oggetto MemoryStream. Quando si utilizza questo tipo di flusso, si verificano problemi nelle risorse di memoria alla ricezione di flussi di dati di dimensioni molto elevate da parte del servizio.

  • Quando si archiviano le risorse multimediali in un database, occorre tenere presente le seguenti considerazioni.

    • Nel modello di dati non devono essere incluse le proprietà binarie che sono risorse multimediali. Tutte le proprietà esposte in un modello di dati vengono restituite nell'elemento entry di un feed di risposta.

    • Per migliorare le prestazioni con flussi binari di grandi dimensioni, è consigliabile creare una classe del flusso personalizzata per archiviare i dati binari nel database. Questa classe viene restituita dall'implementazione di GetWriteStream e invia i dati binari al database in blocchi. Per un database di SQL Server, è consigliabile utilizzare una classe FILESTREAM per trasmettere al database i dati binari di dimensioni superiori a 1 MB.

    • Assicurarsi che il database sia stato progettato per archiviare flussi binari di grandi dimensioni che devono essere ricevuti dal servizio dati.

    • Quando un client invia una richiesta POST per inserire un elemento entry di collegamento multimediale e una risorsa multimediale in una sola richiesta, viene chiamato GetWriteStream per ottenere il flusso prima che il servizio dati inserisca la nuova entità nel database. Un'implementazione del provider di flusso deve essere in grado di gestire questo comportamento del servizio dati. Utilizzare una tabella di dati separata per archiviare i dati binari o archiviare il flusso di dati in un file fino al completo inserimento dell'entità nel database.

  • Quando si implementa il metodo DeleteStream, GetReadStream o GetWriteStream, è necessario utilizzare i valori eTag e Content-Type forniti come parametri dei metodi. Non impostare le intestazioni eTag o Content-Type nell'implementazione del provider IDataServiceStreamProvider.

  • Per impostazione predefinita, il client invia i flussi binari di grandi dimensioni tramite codifica di trasferimento HTTP Chunked. Poiché il server di sviluppo ASP.NET non supporta questo tipo di codifica, non è possibile utilizzare il server Web in questione per ospitare un servizio dati di flusso che debba accettare flussi binari di grandi dimensioni. Per ulteriori informazioni sul server di sviluppo ASP.NET, vedere Web Servers in Visual Web Developer.

Requisiti di versione

Il provider di flusso prevede i seguenti requisiti di versione del protocollo OData:

  • Il provider di flusso richiede che il servizio dati supporti la versione 2.0 del protocollo OData e versioni successive.

  • Il supporto dei flussi denominati richiede che il client e il servizio dati supportino entrambi la versione 3.0 del protocollo OData e versioni successive.

Per ulteriori informazioni, vedere Controllo delle versioni del servizio dati (WCF Data Services).

Vedere anche

Concetti

Provider di servizi dati (WCF Data Services)

Provider di servizi dati personalizzati (WCF Data Services)

Utilizzo di dati binari (WCF Data Services)