Поделиться через


Потоковый поставщик (службы WCF Data Services)

Служба данных может обеспечивать доступ к данным больших двоичных объектов. Эти двоичные данные могут представлять видео- и аудиопотоки, изображения, файлы документов или двоичные данные медиаресурсов других типов. Когда сущность в модели данных включает одно или несколько двоичных свойств, служба данных возвращает двоичные данные в кодировке base-64 в записи в канале ответа. Поскольку загрузка и сериализация больших объемов двоичных данных подобным способом может ухудшить производительность, Протокол Open Data Protocol (OData)  определяет механизм получения двоичных данных независимо от сущности, к которой они относятся. Это достигается отделением двоичных данных от сущности с последующим разделением их на один или несколько потоков данных.

  • Медиаресурсы — это двоичные данные, относящиеся к сущности, такие как видео, аудио, изображения, а также потоки медиаресурсов других типов.

  • Запись медиассылки — это сущность, содержащая ссылку на соответствующий поток медиаресурса.

Службы WCF Data Services позволяет определить двоичный поток ресурса путем определения поставщика потоковых данных. Реализация потокового поставщика предоставляет службе данных поток медиаресурса, связанный с указанной сущностью в качестве объекта Stream. Эта реализация позволяет службе данных принимать и возвращать медиаресурсы по протоколу HTTP в виде потоков двоичных данных с указанным типом MIME.

Настройка службы данных для поддержки потоков двоичных данных состоит из следующих этапов.

  1. Определите одну или несколько сущностей в модели данных как медиассылки. Эти сущности не должны содержать двоичные данные, предназначенные для преобразования в поток. Любые двоичные свойства сущности всегда возвращаются в записи в виде кодировки base-64.

  2. Реализует интерфейс T:System.Data.Services.Providers.IDataServiceStreamProvider.

  3. Определите службу данных, использующую интерфейс IServiceProvider. Для доступа к реализации поставщика потоковых данных в службе данных используется реализация GetService. Этот метод возвращает соответствующую реализацию потокового поставщика.

  4. Разрешите большие потоки сообщений в настройке веб-приложения.

  5. Включите доступ к двоичным ресурсам на сервере или в источнике данных.

Примеры в этом разделе основаны на образце потоковой службы хранения фотографий, которая подробно обсуждается в публикации Ряд потоковых поставщиков служб данных. Реализация потокового поставщика (часть 1). Исходный код для этого образца службы представлен на странице Образец службы данных для хранения фотографий на сайте MSDN Code Gallery.

Определение медиассылки в модели данных

Поставщик источника данных устанавливает способ, которым сущность определяется как медиассылка в модели данных.

  • Поставщик 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>
    

    Необходимо также добавить пространство имен xmlns:m=https://schemas.microsoft.com/ado/2007/08/dataservices/metadata либо в сущность, либо в корень EDMX- или CSDL-файла, определяющего модель данных.

    Пример службы данных, в которой используется поставщик Entity Framework и которая предоставляет доступ к медиаресурсу, см. в публикации Ряд потоковых поставщиков служб данных. Реализация потокового поставщика (часть 1).

  • Поставщик отражения
    Чтобы указать, что сущность является медиассылкой, добавьте HasStreamAttribute к классу, определяющему тип сущности в поставщике отражения.
  • Специализированный поставщик службы данных
    При использовании специализированных поставщиков службы данных необходимо реализовать интерфейс IDataServiceMetadataProvider, чтобы определить метаданные для службы данных. Дополнительные сведения см. в разделе Специализированные поставщики служб данных (службы WCF Data Services). Необходимо указать, что двоичный поток ресурса принадлежит к типу ResourceType. Для этого свойству IsMediaLinkEntry задается значение true применительно к типу ResourceType, представляющему тип сущности, которая является записью медиассылки.

Реализация интерфейса 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, который возвращает экземпляр класса PhotoServiceStreamProvider, реализующего IDataServiceStreamProvider.

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 Windows Communication Foundation (WCF) используется для предоставления реализации протокола HTTP. По умолчанию WCF ограничивает размер сообщений HTTP значением всего лишь 65 КБ. Чтобы иметь возможность направлять большие потоки двоичных данных в службу данных и из нее, необходимо также настроить веб-приложение, включив возможность использования больших двоичных файлов и потоков для передачи. Для этого добавьте к элементу <configuration /> файла Web.config приложения следующее.

 <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(ru-ru,VS.100).gifПримечание
Необходимо использовать режим передачи System.ServiceModel.TransferMode.Streamed, чтобы обеспечить для двоичных данных запроса и ответа потоковую передачу и отсутствие буферизации WCF.

Дополнительные сведения см. в разделах Streaming Message Transfer и Transport Quotas.

По умолчанию службы IIS также накладывают на размер запроса ограничение в 4 МБ. Чтобы обеспечить службе данных, работающей под управлением IIS, возможность приема потоков размером более 4 МБ, необходимо также задать атрибут maxRequestLength элемента httpRuntime Element в разделе конфигурации <system.web />, как показано в следующем примере:

  <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. Также можно кэшировать сущность и вносить обновления в модуль удаления, такие как установка для свойства значения, равного заголовку Slug в запросе POST.

  • После приема запроса POST служба данных вызывает метод GetWriteStream для создания медиаресурса перед вызовом SaveChanges для создания медиассылки.

  • Реализация GetWriteStream не должна возвращать объект MemoryStream. При использовании потока подобного типа будут возникать проблемы, связанные с использованием памяти, во время получения очень больших потоков данных.

  • Следующие факторы следует учитывать при хранении медиаресурсов в базе данных:

    • Двоичное свойство, являющееся медиаресурсом, не должно включаться в модель данных. Все свойства, предоставляемые в модели данных, возвращаются в записи в канале ответа.

    • Чтобы улучшить производительность при работе с большим двоичным потоком, рекомендуется создать пользовательский класс потока для хранения двоичных данных в базе данных. Этот класс возвращается посредством реализации GetWriteStream и отправляет двоичные данные в базу данных в виде фрагментов. Для базы данных SQL Server рекомендуется использовать FILESTREAM для отправки данных потоками в базу данных, когда размер двоичных данных превышает 1 МБ.

    • Убедитесь в том, что база данных предусматривает хранение больших двоичных потоков, получаемых используемой службой данных.

    • Когда клиент отправляет запрос POST для вставки медиассылки и медиаресурса в одном запросе, для получения потока вызывается метод GetWriteStream перед тем, как служба данных вставит новую сущность в базу данных. Реализация потокового поставщика должна уметь работать с таким поведением службы данных. Рассмотрите возможность использования отдельной таблицы данных для хранения двоичных данных или хранения потока данных в файле до вставки сущности в базу данных.

  • При реализации методов DeleteStream, GetReadStream или GetWriteStream необходимо использовать значения eTag и Content-Type, предоставляемые в качестве параметров метода. Не устанавливайте заголовки eTag или Content-Type в реализации поставщика IDataServiceStreamProvider.

  • По умолчанию клиент отправляет большие двоичные потоки, используя фрагментированный HTTP Transfer-Encoding. Поскольку сервер разработки ASP.NET не поддерживает данный тип кодировки, нельзя использовать этот веб-сервер для размещения потоковой службы данных, предназначенной для приема больших двоичных потоков. Дополнительные сведения о сервере разработки ASP.NET см. в разделе Web Servers in Visual Web Developer.

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

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

  • Потоковый поставщик требует, чтобы служба данных поддерживала версию 2.0 протокола OData и последующие версии.

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

См. также

Основные понятия

Поставщики служб данных (службы WCF Data Services)
Специализированные поставщики служб данных (службы WCF Data Services)
Работа с двоичными данными (службы WCF Data Services)