ADO.NET Data Services: CLR-based data models and navigation links

As you are probably aware, one of the new additions to the .NET Framework 3.5 SP1 is a technology called ADO.NET Data Services (code name Astoria). ADO.NET Data Services natively supports ADO.NET Entity Framework (EF) models. However Data Services it is not limited to EF.

ADO.NET Data Services can deploy consistent representations of data regardless of the underlying data source. This approach has made CLR-based data models first class citizens. See here for a comprehensive guide on using CRL-based data models.

Imagine the following class diagram that represents two entities:

 

As you can see, Library has a collection of Books. Therefore Library.Books can be considered a one-to-many resource navigation link to a collection of Books.

public class Library

{

  public int LibraryID { get; set; }

  public string LibraryName { get; set; }

  public List<Book> Books { get; set; }

}

public class Book

{

  public int BookID { get; set; }

  public string BookTitle { get; set; }

}

A simple Data Services’ resource container exposing a list of libraries may look similar to the following:

public class LibraryDataModel

{

  static List<Library> s_libraries = ...;

  public IQueryable<Library> Libraries

  {

    get

    {

      return s_libraries.AsQueryable();

    }

  }

}

Unfortunatly exploring this data model – by perhaps browsing to the URI that exposes this model – may fail throwing an exception similar to the following:

Request Error: The server encountered an error processing the request. The exception message is 'The property 'Books' on type 'AstoriaWeb.Library' is not a valid property. Properties whose types are collection of primitives or complex types are not supported.'

This means that ADO.NET Data Services was not able to automatically consider Books as a resource set that can be referenced using resource navigation links from Library resources. In fact, without some more information, it is really hard for Data Services to automatically expose a new resource set through a resource container.

So how can you avoid this? For this release of Data Services at least, you need to explicitly expose Books as a resource set in the resource container:

public class LibraryDataModel

{

  static List<Library> s_libraries = ...;

  static List<Book> s_books = ...;

  public IQueryable<Library> Libraries

  {

    get

    {

      return s_libraries.AsQueryable();

    }

  }

  public IQueryable<Book> Books

  {

    get

    {

      return s_books.AsQueryable();

    }

  }

}

This article was written based on .NET Framework 3.5 SP1 Beta.

Comments

  • Anonymous
    July 19, 2008
    PingBack from http://wordnew.acne-reveiw.info/?p=11018

  • Anonymous
    September 29, 2008
    That's nice. But.. Where would you make possible database calls to fill s_libraries and s_books? You could do this in the constructor, but that would lead to the fact that all data would be retrieved on every request. Not good. Ideally, you'd to this in the get for Books, for instance: public IQueryable<Book> Books  {    get    {      using(DataSource dataSource = new DataSource)      {         return dataSource.Books.AsQueryable();      }    }  } But that leads to an exception: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. Any thoughts appreciated. koen

  • Anonymous
    October 30, 2008
    hi, I have created some of the SP and function in .net....i can depoly this to SQL CLr using deply menu in VS2005 or i can use create assembly method to add the dll into SQL CLr.... but i want to send this to client....is there any MSI i can build so the client can run the same as exe... Regards Raag

  • Anonymous
    January 25, 2009
    Thanks for the info.  Your post cleared up the data model used to shoehorn non-entity objects into data services.  All their examples had it, but none of the samples explicitly stated that every object has to be part of these root collections.