Welcome! In this series of articles, I am going to show you how to perform some advanced OData/WCF Data Service tasks, such as creating a custom data service
provider, customizing the generation of service references, and more. First, I will describe some of the limitations of WCF Data Services and then how we will address them.
Limitations of WCF Data Services
WCF Data Services are great, but currently have a few key limitations:
- It is difficult to aggregate many data sources into a single data service.
- It is very hard to augment WCF Data Services with standard WCF Services.
- No client-side proxies are generated for service operations.
There are some more subtle limitations that we'll see later.
Running the Example Service
Here's how to get started with the sample service:
- Open the CompositeDataServiceFramework Solution.
- Double click on the file Samples > Composite Data Service Sample > CreateDatabases.sql.
- Run this script (SQL Server Express Edition is fine as a database platform if you do not have the full MS SQL Server installed).
- Run the CompositeDataServiceSample project.
- Browse to http://localhost:65110/CompositeDataServiceSample.svc/$metadata and we can see
that the CompositeDataService has composed a single data service from our Orders and Users Data services - and that the service is fully functional.
The Composite Data Service Framework
With these limitations in mind, I have created a project called the Composite Data Service Framework. The main aim of this project is to allow many data
sources to be aggregated together to create a single composite WCF Data Service, highlighted by the diagram below.
Creating a Composite Data Service
Creating a composite data service is very simple. First, add a WCF Data Service class for each model you want to expose - in the example solution provided,
I have two Models - an
OrdersDataModel and a
UsersDataModel. These models are Entity Framework Data Models. Now create another WCF Data Service,
named something like '
CompositeDataService'. All you now need to do is derive from
CompositeDataService and add each distinct WCF Data Service
Here's how we do it step-by-step.
First, create the Composite Data Service, by adding a WCF Data Service to your application:
public class CompositeDataServiceSample :
private WcfDataServiceDataSource<OrdersModelContainer> ordersDataService;
private WcfDataServiceDataSource<UsersDataModelContainer> usersDataService;
What we have done here is create a composite data service that has two data source members - one for our users model and one for our orders model. Next we
initialise our service just as we would any normal WCF Data Service - specifying access for each object and operation.
public static void InitializeService(DataServiceConfiguration config)
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
Finally, in the constructor, we build the two data sources and add them to the composite data service and then initialise it.
ordersDataSource = new WcfDataServiceDataSource<OrdersModelContainer>(
usersDataSource = new WcfDataServiceDataSource<UsersDataModelContainer>(
Now you can run up the data service and put /$metadata at the end of the URL - this single data service aggregates the two other data services into one!
Now when you add a reference to the composite data service in a client project, you have access to entities from both services; from the client's point of view,
it doesn't matter where they come from, they are presented as part of the same service.
How Does It Work?
There is a lot of code in this project already, and there's going to be more as I build up the full set of features. So rather than going through the code
line-by-line as I do in most of my articles, I'm going to describe the code in a more high level way.
Creating a Custom Data Service
The first thing to do is to derive a class from Data Service.
This will be the the main object that represents the Composite Data Service. This object must also implement the
IServiceProvider interface, to allow instances of supporting interfaces to be instantiated.
The following interfaces must now be supported (in this framework, each is in its own class).
exposes information about the service itself - what collections it exposes, the object types it exposes, its service operations, and relationships between objects.
allows actual querying of the data in a data service. The most important function of the lot
which must return an
IQueryable for a specific resource set.
IDataServiceUpdateProvider interface exposes functions to enable
manipulation of the data we have defined in the Metadata Provider and exposed in the Query Provider. It allows data to be updated, deleted, etc.
Keeping Up To Date
The Composite Data Service Framework is hosted on CodePlex at: http://cdsf.codeplex.com/. The roadmap
for the project is on the main page. I would welcome any suggestions or ideas! As this project develops, we will be completing the following tasks:
- Allow an Entity Framework Model to be used as a Composite Data Source - without the need for a WCF Data Service to expose it first.
- Allow collections of standard CLR objects to be used as a Composite Data Source.
- Demonstrate customization of creating of the client-side Service Reference by showing how to create a special attribute used client side to mark a property as client-side only.
- Demonstrate how Service Operation proxies can be generated automatically when adding the service reference.
- Show how to extend Visual Studio with custom templates for items, projects, and show how to use Wizards to customize the generation of these items.
There is a great set of posts on Alex D James' blog 'Meta-Me' describing how to create custom data services - the first post
is here: http://blogs.msdn.com/b/alexj/archive/2010/01/07/data-service-providers-getting-started.aspx.
The Composite Data Service Framework is hosted on CodePlex at: http://cdsf.codeplex.com/.
I post various articles about the ongoing development of my projects on my blog: http://www.dwmkerr.com.