Using OData protocol V3 with MongOData OData provider

In a recent post I showed how MongOData (it’s a MongoDB OData provider that I wrote and maintain) exposes BsonArray MongoDB properties. Support for arrays of primitive and complex types has been added to OData protocol in its latest version 3, but many clients and code generation tools haven’t been enhanced with this feature, so they will fail accessing a MongoDB collection where some items are exposed as arrays.

Moreover, due to the nature of document databases, array is a natural way of exposing collections of items, versus one-to-many relationship used in relational database. So the chances are pretty high that an arbitrary MongoDB repository will contain documents that will break old generation client tools.

Let me show you this on a simple example. I’ve been working on a set of MongOData samples that would illustrate how to set up and use the provider, and once I tried to generate a WCF Data Services client proxy using Visual Studio 2010, it showed me the following error message:

DataServiceVersionError

The offending part was the Product class definition that contained an array of Suppliers:

public class Supplier
{
    public string Name { get; set; }
    public Address[] Addresses { get; set; }
}

So what can you do to overcome such limitation? It’s really silly not to be able to retrieve data structure that both service can expose and your code can consume when all that stops you is a man in the middle: a proxy generation tool.

My answer to this is simple: bypass proxy generation. OData protocol follows REST principles, and proxy generation is so SOAP. Just use C# dynamics so the service metadata will be evaluated at runtime.

One simple approach to achieve this is to use Simple.Data OData adapter. Here’s the code that retrieves the content of MongoDB collection (containing arrays) using Simple.Data:

Console.WriteLine("Connecting to MongoDB sample OData service...");
dynamic context = Database.Opener.Open("http://localhost:50336/MongoDataService.svc/");

Console.WriteLine("Retrieving categories...");
Console.WriteLine();
foreach (var category in context.Categories.All().ToList())
{
    Console.WriteLine("Category: ID=[{0}], Name=[{1}]",
        category.ID,
        category.Name);
}
Console.WriteLine();

Console.WriteLine("Retrieving products...");
Console.WriteLine();
foreach (var product in context.Products.All().ToList())
{
    Console.WriteLine("Product: ID=[{0}], Name=[{1}], Category=[{2}], Quantity=[{3} {4}], " +
                      "ReleaseDate=[{5}], DiscontinueDate=[{6}], Suppier=[{7}]",
        product.ID,
        product.Name,
        product.Category.Name,
        product.Quantity.Value,
        product.Quantity.Units,
        product.ReleaseDate,
        product.DiscontinueDate,
        product.Supplier == null ? null : product.Supplier.Name);
}

I created MongOData.Samples solution with the following projects:

  • CreateSampleData – creates a sample MongoDB database (default connection string is set to mongodb://localhost/mongodatasamples, you can of course change it), during creation is asks if you want to enable OData protocol V3 support;
  • SampleService – WCF Data Service provider that uses MongOData to connect to a MongoDB instance;
  • SampleWcfDataServiceClient – OData client that uses proxy classes generated by Visual Studio, so it can not consume services that use OData V3 features such as arrays;
  • SampleDynamicClient – proxy-less client that uses Simple.Data OData adapter and support OData V3 features.

You can download sample solution here.

One thought on “Using OData protocol V3 with MongOData OData provider”

  1. Hi Peter,

    Of course in case you use dynamic libraries like Simple.Data, you use dynamic C# instead of LINQ queries. But the only thing you lose is compile-time generated proxy, and in my opinion this is the advantage. If you prefer having generated proxy code, you can point Visual Studio to a MongOData service and it will produce C# proxy… unless your OData service happen to have specific V3 features like arrays. Then the only way is proxy-less approach as described in this post.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>