Creating a Data Service Provider – Part 6 – Query Interactions

Whenever I find myself implementing a series of interfaces to plug into a framework or server, I always find myself wondering how the server will call my implementations.

For me this is about forming a mental model to simplify how I think about what I’m doing.

In fact as I’ve been doing this DSP series I’ve come up with a sort of mental model for how Queries are handled in a Data Service.

Here is some PSEUDO CODE that captures my mental model of how these interfaces interact.

Scenario – Basic Query

Imagine a client issues a GET request for /Sample.svc/Products(1)

The first thing that happens (in my model) is that the data service is initialized.

// Locate the IDSP interfaces
var dataservice = …;
IServiceProvider sp = dataservice as IServiceProvider;
if (sp == null)
{
// some other code I’ll go into another day !!!
}

// Get the various DSP interface implementations
IDataServiceMetadataProvider mdp =
sp.GetService(typeof(IDataServiceMetadataProvider));
IDataServiceQueryProvider qp =
sp.GetService(typeof(IDataServiceQueryProvider));

// Set the CurrentDataSource (if necessary)
if (qp.CurrentDataSource == null)
qp.CurrentDataSource = dataservice.CreateDataService();

// Find the Products resourceSet
// (note we actually try for ServiceOperations first
// but lets keep this simple)
var resourceSet = null;
if (!mdp.TryResolveResourceSet(“Products”, out resourceSet))
throw new Exception(“404”);

// Get the queryable for the Products resourceSet
IQueryable queryRoot = qp.GetQueryRootForResourceSet(resourceSet);

// Compose expressions onto the IQueryable to represent the
// options ($filter/$select etc) specified in the URL
queryRoot = Compose(options, queryRoot);

// Start writing response
WriteStartODataFeed();

// Enumerate results
foreach (object resource in queryRoot)
{
// Get the ResourceType for resource
// NOTE: because of inheritance it might be a resourceType
// derived from resourceSet.ResourceType
ResourceType type = qp.GetResourceType(type);
WriteResource(resource,type);
}
WriteEndODataFeed();

That’s it take it or leave it.

Hopefully you found this ‘completely made up’ code useful for forming your own mental model of how your DSP will fit into the Data Services framework.

Next time

There are some things I’ve left out of the above ‘mental model’ for now, like how ServiceOperations and QueryInterceptors complicate things.

We’ll flesh more of those complications out in future posts.

Next time though it’s time to take our Read/Only strongly typed ResourceSet and make it Read/Write.