0

I have a WCF WebService that uses LINQ and EF to connect to an SQL database. I have an ASP.NET MVC front end that collects its data from the webservice.

It currently has functions such as

List<Customer> GetCustomers();

As the number of customers increases massively the amount of data being passed increases also reducing efficiency. What is the best way to "page data" across WebServices etc.

My current idea is to implement a crude paging system such as

List<Customer> GetCustomers(int start, int length);

This, however, means I would have to replicate such code for all functions returning List types. It is unfortunate that I cannot use LINQ as it would be much nicer.

Does anyone have any advice or ideas of patterns to implement that would be "as nice as possible". Also how would one cope with such things as ordering. I.e. if I want to order by a specific parameter I would have to implement something bespoke for each type which seems wasteful.

Thanks

Chris
  • 26,744
  • 48
  • 193
  • 345

3 Answers3

1

I haven't done this before with WCF, but the following should work:

  1. Define a DataContract type containing start and length properties.
  2. Declare it as a SOAP Header to be used in all of the data retrieval operations.
  3. Write an extension method on IEnumerable<T> that accepts the SOAP Header object. This method would return enumerable.Skip(start).Take(length).
  4. Call the extension method in the return from each data retrieval method.
John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • Hey John, thanks for the reply - How does this play with WCF? Sounds like a lot of customisation on the WCF side of things? I'm not even sure how to go about this? – Chris Jan 04 '11 at 16:01
  • It plays perfectly. It's not even a customization, per se. SOAP Headers are a standard part of SOAP, designed for exactly this sort of thing: passing "out of band" information to and/or from a service, so that you don't have to have "start, length" parameters to everh list-returning operation: you put them in the header instead. Another example of a header would be a service that requires a security token on every request. You don't want to add that parameter to every method, so it is put in the header. – John Saunders Jan 04 '11 at 16:04
  • Ok sounds great - I don't suppose I could trouble you for some pointers on how to implement such things? – Chris Jan 04 '11 at 16:10
  • See the accepted answer to http://stackoverflow.com/questions/1976217/how-to-add-custom-soap-headers-in-wcf. The answer is "message contracts". I found this in a quick Bing search for "wcf soap headers". – John Saunders Jan 04 '11 at 16:16
  • Thank you, Bing: [Using Message Contracts](http://msdn.microsoft.com/en-us/library/ms730255.aspx). – John Saunders Jan 04 '11 at 16:19
1

The only code you would need to replicate would be the method signature ((int start, int length), and a call to .Skip(start).Take(length). Because these are very expressive of what you're actually trying to do, I wouldn't consider this to be too much repetition.

One other thing you may want to look into is OData endpoints, which allow you to construct a query, complete with filters and paging, on some subset of your data source via a URL. For an example, see:

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
0

You may be interested in streaming WCF responses (see requirements for streaming). By default, messages are buffered, but a stream can help ease the pain, and push data out as its being fetched. Its very easy to configure:

<basicHttpBinding>
    <binding name="StreamingBinding" 
        transferMode="StreamedRequest"  
        maxBufferSize="65536"
        maxReceivedMessageSize="204003200"  />
</basicHttpBinding>

<service behaviorConfiguration="behaviorConfig" name="serviceName">
    <endpoint address="http://whatever" 
        binding="basicHttpBinding" 
        bindingConfiguration="StreamingBinding" 
        contract="IServiceContract" />
</service>
Juliet
  • 80,494
  • 45
  • 196
  • 228