WCF and large hierarchical data

If you need to send large amount of information using a single WCF call, you will need to customize binding configuration that is by default tuned for efficient transfer of small messages. And if your data contracts happen to have types with circular (or self-) references, this behavior needs to be configured too. Here what I had to tweak in order to enable transfer of very large (up to 100 MB) collections of hierarchical data.

1. Binding configuration

The following binding attribute may need adjustments:

  • maxBufferSize
  • maxBufferPoolSize
  • maxReceivedMessageSize
  • openTimeout
  • closeTimeout
  • sendTimeout
  • receiveTimeout

Binding element has “readerQuotas” sub-element where the following attributes may be tweaked for large amount of data transfer:

  • maxDepth
  • maxStringContentLength
  • maxArrayLength
  • maxBytesPerRead
  • maxNameTableCharCount

In addition, transferMode can be set to either “Buffered” or “Streamed” depending on how data should be received by the client.

2. Behavior configuration

In case large amount of data are sent as standard collections (arrays, lists etc.), no behavior customization is needed in order to increase data transfer limits. But if the data represent more complex topology, there is an additional attribute to adjust, and this attribute belongs to behavior, not binding. It is called “maxItemsInObjectGraph” and can be specified either on serviceBehavior or endpointBehavior level. The customize behaviors element may look like this:

<behaviors>
	<servicebehaviors>
		<behavior name="LargeTreeBehavior">
			<servicedebug includeexceptiondetailinfaults="true" />
			<datacontractserializer maxitemsinobjectgraph="2147483647" />
		</behavior>
	</servicebehaviors>
	<endpointbehaviors>
		<behavior name="HighlightBehaviorLarge">
			<datacontractserializer maxitemsinobjectgraph="2147483647" />
		</behavior>
	</endpointbehaviors>
</behaviors>

3. Serialization of object graphs with circular references

.NET 3.5 SP1 introduced a new attribute IsReference that can be used with DataContracts to enable serialization of object graphs with circular references. Previously it was not possible without writing custom code. Now it requires only a single attribute specification:

[DataContract(IsReference = true)]
public class Node
{
	[DataMember]
	Node Parent { get; set; }
	....
}

That should be it. Now you can send graphs with millions of nodes over the wire using WCF. In may cases sending so much data in a single call is not a good idea, but that’s another topic.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s