2011-03-17 26 views
6

Tenemos un servicio WCF que ejecuta ciertos procedimientos almacenados y devuelve los resultados al cliente silverlight. Algunos de los procedimientos almacenados retornan hasta 80K filas.Tamaño del búfer en el servicio WCF

A continuación se presentan los ajustes en web.config de servicio

<system.serviceModel> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> 
    <behaviors> 
     <serviceBehaviors> 
      <behavior name="MyService.MyServiceBehavior"> 
       <serviceMetadata httpGetEnabled="true"/> 
       <serviceDebug includeExceptionDetailInFaults="true"/> 
       <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
      </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <basicHttpBinding> 
      <binding name="BasicHttpBinding_MyService" 
       maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" 
       receiveTimeout="00:40:00" openTimeout="00:40:00" 
       closeTimeout="00:40:00" sendTimeout="00:40:00"> 
       <readerQuotas maxDepth="2147483647" 
        maxStringContentLength="2147483647" maxArrayLength="2147483647" 
        maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/> 
       <security mode="None"/> 
      </binding> 
     </basicHttpBinding> 
     <customBinding> 
      <binding name="MyService.MyService.customBinding0"> 
       <binaryMessageEncoding/> 
       <httpTransport/> 
      </binding> 
     </customBinding> 
    </bindings> 
    <services> 
      <service behaviorConfiguration="MyService.MyServiceBehavior" 
        name="MyService.MyService"> 
       <endpoint name="BasicHttpBinding_MyService" 
        address="" 
        binding="basicHttpBinding" 
        bindingConfiguration="BasicHttpBinding_MyService" 
        contract="MyService.IMyService"/> 
      </service> 
    </services> 
</system.serviceModel> 

Y esto por cliente

<system.serviceModel> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> 
    <behaviors> 
     <serviceBehaviors> 
      <behavior name="MyService_Behavior"> 
       <serviceDebug includeExceptionDetailInFaults="true"/> 
       <serviceMetadata httpGetEnabled="true"/> 
      </behavior> 
     </serviceBehaviors> 
     <endpointBehaviors> 
      <behavior name="r1"> 
       <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
      </behavior> 
     </endpointBehaviors> 
    </behaviors> 
    <bindings> 
     <basicHttpBinding> 
      <binding name="BasicHttpBinding_MyService" 
       closeTimeout="00:03:00" openTimeout="00:03:00" 
       receiveTimeout="00:10:00" sendTimeout="00:03:00" 
       allowCookies="false" bypassProxyOnLocal="false" 
       hostNameComparisonMode="StrongWildcard" 
       maxBufferSize="2147483647" maxBufferPoolSize="2147483647" 
       maxReceivedMessageSize="2147483647" 
       messageEncoding="Text" textEncoding="utf-8" 
       transferMode="Buffered" useDefaultWebProxy="true"> 
       <security mode="None"/> 
      </binding> 
     </basicHttpBinding> 
    </bindings> 
    <client> 
     <endpoint name="BasicHttpBinding_MyService" 
      address="http://localhost:8080/MyService/MyService.svc" 
      behaviorConfiguration="r1" 
      binding="basicHttpBinding" 
      bindingConfiguration="BasicHttpBinding_MyService" 
      contract="MyService.IMyService" /> 
    </client> 
</system.serviceModel> 

Siempre que el número de registros van más allá de 20K, el servicio genera un error, ya sea como tiempo de espera o NotFound. ¿Por qué crees que sucede esto? ¿Cómo lo soluciono?

+1

¿Seguro que desea devolver 80K filas de una llamada? Tal vez la refacturación y el uso de resultados "paginados" serían más apropiados. – Jon

+0

Sé que suena absurdo, pero mis usuarios están empeñados en que se muestre en la grilla (por supuesto, los mostramos con paginación). La mayoría de las cuadrículas de terceros como Telerik lo admiten aunque – Kev

+0

Puede tratar de obtener esa información en llamadas múltiples DownloadPage (1) ... n obtendrá todos los datos pero en trozos más pequeños – kalvis

Respuesta

3

Parece una gran sobrecarga de datos. La paginación, como se señala en los comentarios, es una solución práctica. Si hay una buena razón para querer el 80k, podría intentar usar un mecanismo diferente para serializar los datos. Por ejemplo, los datos de protobuf generalmente son mucho más pequeños que xml, por lo que puede intentar usarlos en el cable. Sin embargo, como esto es Silverlight, no puedo (actualmente) intercambiar esto automáticamente, necesitaría devolver un byte[] o Stream y manejar la serialización/deserialización explícitamente en el servidor/cliente. Esto debería reducir los requisitos de ancho de banda con un golpe justo (incluso más si puede configurar Silverlight para usar MTOM; no lo he comprobado recientemente, pero esto no era compatible con algunas versiones anteriores).

+0

Estoy de acuerdo con esta respuesta. En el futuro, la mejor manera de mostrar los resultados sería obtener cantidades de datos más pequeñas a medida que el usuario busca en la página siguiente. Pero en este momento, necesito una solución rápida ya que este problema ocurre en un sistema de producción. – Kev

+1

@Kev usted * podría * tener suerte y encontrar la manera de hacerlo, pero no todo puede abordarse con una solución rápida. Es * posible * que sea más rápido dejar de perder tiempo buscando una solución rápida, y simplemente solucione el problema subyacente. –

2

Como su proc devuelve 80K, también debe agregar el tamaño de su búfer en el extremo del cliente.

readerQuotas

<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/> 

Esto debería funcionar. Si es necesario, aumente el tamaño de su búfer.

1

Hemos utilizado con éxito la compresión GZIP entre el cliente y el servicio WCF para aumentar la cantidad de filas que podríamos retirar. También debería funcionar para sus necesidades.

Utilizamos las bibliotecas MS para lograrlo: http://msdn.microsoft.com/en-us/library/ms751458.aspx

Cuestiones relacionadas