Partager via


Custom Data Service Providers

Introduction

Data Services sits above a Data Service Provider, which is responsible for interacting with the underlying Data Source on behalf of the Data Service.

Data Services ships with some internal providers, and makes it possible for you to create custom providers too.

So the obvious question is...

Do you need a Custom Data Provider?

Creating a Custom Data Service Provider is a fair amount of work, which of course provides big dividends like, allowing people to:

  • Query and manipulate your data via the Data Services Client in:
    • WPF
    • WinForms
    • SilverLight
    • etc
  • Query you data directly via a browser
  • Query and manipulate your data via Javascript and associated frameworks like JQuery
  • Query your data via knowledge worker tools like PowerPivot.
  • etc.etc.etc.

But before you jump into creating a custom provider, see if you fall into one of the following camps, all of which have a much easier solution:

Entity Framework

If you plan on putting a Data Service over the Entity Framework the answer is no you don't need to write a custom provider.

Data Services has an implementation that talks to the Entity Framework in the box.

You simply point your DataService at your strongly typed ObjectContext, and that’s it:

public class NorthwindDataService:
DataService<NorthwindEntities>

In this example NorthwindEntities is your strongly typed ObjectContext representing the Northwind database.

For a good example of an OData Service built using the Entity Framework check out this post.

LINQ to SQL

If you want to create a Data Service over a LINQ to SQL data source you should take a look at this project on Code Gallery.

It includes sample code you can use to extend your strongly typed DataContext class to implement the IUpdatable interface.

This in conjunction with the Reflection Provider means you can use your LINQ to SQL DataContext just like an Entity Framework ObjectContext:

public class NorthwindDataService:
DataService<NorthwindDataContext>

Reflection Provider

If you have your own class that can represent your Data Source, and it has a number of strongly typed IQueryable properties like this:

public class MyDataSource
{
public IQueryable<Product> Products { get {…} }
public IQueryable<Categories> Categories { get {…} }
}

The built-in reflection provider can turn this into a read-only service and infer ResourceSets, Types and Properties automatically.

You can even make this read-write by extending your class to implement IUpdatable:

public class MyDataSource: IUpdatable

In fact this is exactly how the LINQ to SQL example above works.

For a good example of an OData Service created using the reflection provider check out Tip 56.

So when do you actually need a custom provider?

The reflection provider is very useful for some scenarios.

But is has a number of limitations that might disqualify it for your scenario:

  1. It is static, i.e. the shape of the service can’t evolve over time.
  2. It needs CLR classes for each ResourceType, which you might not have.
  3. It needs to find Id or {Type}Id properties to use as keys.
  4. It blindly exposes all public properties of the CLR classes.
  5. It gives you less control over streaming or paging.
  6. You can’t take advantage of advanced features like Open Types, which allows resources to optionally include more Open Properties.
  7. You have less control, for example you can't log requests as easily or modify metadata or rename properties
  8. etc. etc. etc.

If any of these are important it’s time to create a Custom Data Service Provider…

Creating a Data Service Provider Series

This series of posts will grow to cover all of the major DSP interfaces and show case lots of scenarios

Part 1 – Intro
Part 2 – IServiceProvider and DataSources
Part 3 – IDataServiceMetadataProvider 
Part 4 – Minimal Running Service
Part 5 – Query
Part 6 – Query Interactions
Part 7 – Updates
Part 8 - Relationships
Part 9 - Untyped

possible future installments…

Part 10 – ETags
Part 11 – Friendly Feeds
Part 12 – Streaming
Part 13 – Advanced Paging

Comments

  • Anonymous
    February 15, 2010
    Hi,I just played with WCF Data Services and the expectations I had related to the term WCF were more than disappointed.ADO.Net Data Services were renamed by far too early.http://my-tech-talk.blogspot.com/2010/02/enjoy-wcf-data-services-sandwich.htmlYou have any ideas, when there will be a WCF WCF Data Service Provider that allows me to actually publish WCF Data Contracts types over WCF Data Services? This would be my minimum expectation I would like to see fulfilled before I'd call it WCF.Cheers,Tobias
  • Anonymous
    February 15, 2010
    Tobias,I hear you. We are working to bring Data Services and WCF closer together. The rename essentially signals intent.Alex
  • Anonymous
    May 29, 2010
    Great series, I managed to get my custom implementation running, but I'm stuck at the IDataServiceStreamProvider right now. Reading is easy, but doing the SetWriteStream isn't :p Hope you can make it to the future chapters soon :)
  • Anonymous
    June 08, 2010
    Is the source code available somewhere?  I know C# and ASP.Net Web services but I’m new to OData and WCF Services.  I've entered the code from the walkthrough and it compiles but the web site didn’t do anything.  I think somehow I'm missing some glue such that the code is actually called when I try and access the web site.  I took a guess that for the Sample class I needed to create not just a normal C# class but rather add a WCFService to my project.  I tried that and started getting a bunch of errors so I'm doing something wrong but I don't see any steps I might have missed from the walkthrough.  (When I made my modification and made Sample by adding a WCF Service to the project I started getting “The operation 'ProcessRequestForMessage' could not be loaded because it has a parameter or return type of type System.ServiceModel.Channels.Message or a type that has MessageContractAttribute and other parameters of different types. When using System.ServiceModel.Channels.Message or types with MessageContractAttribute, the method must not use any other types of parameters.”)
  • Anonymous
    June 09, 2010
    Tom,I don't have the source for this series anywhere... but there is something much better - the odata sdk contains a number of DSP samples - and a walkthru based on this series but tied to the samples that you can use.odata.org/.../odata-sdkHope this helpsAlex
  • Anonymous
    June 09, 2010
    David,I hope I can finish this series soon. Thanks for the reminder :)Alex
  • Anonymous
    June 09, 2010
    David,I hope I can finish this series soon. Thanks for the reminder :)Alex
  • Anonymous
    June 24, 2010
    Chinese Version 中文翻译:www.cnblogs.com/.../1755250.html
  • Anonymous
    March 24, 2011
    Alex can you please point out which aspect of the custom data provider is addressing the "late-binding" feature?Thank you.
  • Anonymous
    March 24, 2011
    Alex, can you please point out which aspect of a custom data provider is addressing the late binding of data types?  Can you elaborate further on what limitations there are?  For instance, I need to expose new  data types as they are introduced at run time.  There is already a data adapter layer in place that returns a data table based on the source type (OLE, Web Services, 3rd party API(s), etc.) so I just need to allow client applications to discover the data type dynamically.I also have the problem where our model is exposed using the Entity Framework but it seems I have to have a separate service implementation to get the data behind the model and it would be nice to provide a unified interface.  This would prevent the client applications from having to handle two different, but related, services.Thank you.Jim
  • Anonymous
    March 24, 2011
    @j_e_oYou should look at part 9. It illustrates how you can have a services without backing CLR types for every data type you expose. This makes it easier to do what you are looking for...However what you want is possible even with a backing CLR type for everything if each time something changes you load a new assembly (not recommending this - just saying it is possible).It is possible because you can return different metadata (and thus different types) to OData for each individual request if you want.
  • Anonymous
    April 09, 2012
    The comment has been removed
  • Anonymous
    June 14, 2012
    Hi Derek,is it possible to download the project you have posted on corememorydump.blogspot.com/.../configurable-odata-service-part-3.html?Markus
  • Anonymous
    August 12, 2012
    The comment has been removed