pátek 21. května 2010

Chyba WCF při velkém počtu záznamů

Nedávno jsem řešil zajímavou chybu ve WCF. Při zobrazení jedné statistiky nahodile padala služba. V logu byla následující chyba:
Maximální počet položek, které lze serializovat nebo převést ze sériového tvaru v grafu objektů, je 65536. Změňte graf objektů nebo zvyšte kvótu MaxItemsInObjectGraph.

Hned bylo jasné, že počet přenášených záznamů je moc velký. Zkoušel jsem měnit konfiguraci dle MSDN, ale nakonec to nebylo tak jednoduché, jak jsem si myslel. Pro ukázku, jak to lze řešit. Důležité je nastavit parametr jak na serveru, tak i na klientovi.
Ukázková konfigurace serveru:

<system.serviceModel>
  <services>
    <service behaviorConfiguration="Umea.se.EventReactor.ServiceTier.ServiceViewEventBehavior" name="Umea.se.EventReactor.ServiceTier.ServiceViewEvent">
      <endpoint address="" binding="wsHttpBinding" contract="Umea.se.EventReactor.ServiceTier.IServiceViewEvent">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="Umea.se.EventReactor.ServiceTier.ServiceViewEventBehavior">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
        <dataContractSerializer maxItemsInObjectGraph="2147483647" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>


A odpovídající konfigurace pro klienta:

<system.serviceModel>
  <client>
    <endpoint address="http://localhost:3379/ServiceViewEvent.svc" behaviorConfiguration="ServiceViewEventBehavior" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceViewEvent" contract="ServiceReferenceViewEvent.IServiceViewEvent" name="WSHttpBinding_IServiceViewEvent">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
  </client>
  <behaviors>
    <endpointBehaviors>
      <behavior name="ServiceViewEventBehavior">
        <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>


Na klientovy je potřeba definovat atribut behaviorConfiguration pro všechny endpointy.