This project is read-only.

Getting started with the Toolkit

The toolkit can be easily implemented in any code base by creating a new service that extends from the ODataContext class, which is located in the Microsoft.Data.Services.Toolkit.QueryModel namespace.
This class forms the base of any service that wishes to implement the OData protocol as a means of transport.

This class has 2 responsabilities that need to be fullfilled in order for the toolkit to be fully working:
  • override the RepositoryFor method
  • Provide IQueryable properties for all supported entities.

Overwriting the RepositoryFor method

In order for the toolkit to be able to determine which class is responsible for storing the data, this method needs to be overloaded.
The goal of the method is to provide a generic mechanism that can determine the specific Repository class that is able to handle the operations for the specified entity.

Below is a code example that will look at the entity type that need to be processed and looks for a repository in a given namespace.
The convention here is that all entities supported by the Service have a matching Repository:
  • User -> UserRepository
  • Car -> CarRepository
  • ...
All these repositories are stored in a single namespace. Using this convention we can use the following code snippet to define a new Context class for the OData service that supports a Car and User entity:
        /// <summary>
        /// <para>This function creates the correct repository implementation to handle the requests
        /// for the specified Entity of the OData API.</para>
        /// <para>Because the entire concept of OData relies on 'convention over configuration', this principle is also
        /// applied to this function. When the fullType name is specified, it will be used to construct the full type 
        /// name of the matching repository. That's why repositories always need to be named 'TypeRepository'.</para>
        /// </summary>
        /// <param name="fullTypeName">The fully qualified name of the Entity who's repository is required.</param>
        /// <returns>The repository implementation for the specified Entity.</returns>
        public override object RepositoryFor(string fullTypeName)
        {
            string typeName = fullTypeName.Replace("[]", string.Empty).Substring(fullTypeName.LastIndexOf('.') + 1);
            Type repoType = Type.GetType(string.Format("My.Demo.Namespace.{0}Repository", typeName));
            if(repoType == null) throw new NotSupportedException(@"The specified type is not an Entity inside the OData API");
            return Activator.CreateInstance(repoType);
        }

Provide IQueryable properties

All entities that are supported in the Service need to be declared on the Context class as well.
In the example we're working with a User and Car entity, the example code will be come something like this:

        /// <summary>
        /// <para>Gets a queryable collection containing User entities for the OData WebService.</para>
        /// </summary>
        public IQueryable<User> User{ get { return CreateQuery<User>(); } }

        /// <summary>
        /// <para>Gets a queryable collection containing Carentities for the OData WebService.</para>
        /// </summary>
        public IQueryable<Car> Cars{ get { return CreateQuery<Car>(); } }


This will result in the Cars and Users url becoming available on the service:
  • Users => http://<applicationurl>/Api.svc/Users
  • Cars => http://<applicationurl>/Api.svc/Cars

Complete example

Below is a code snippet that contains a complete example of a Context class that supports a Car and User entity in the OData service.

    public class Context : Microsoft.Data.Services.Toolkit.QueryModel.ODataContext
    {
        #region Entities

        /// <summary>
        /// <para>Gets a queryable collection containing <see cref="User"/> entities for the OData WebService.</para>
        /// </summary>
        public IQueryable<User> Users{ get { return CreateQuery<User>(); } }

        /// <summary>
        /// <para>Gets a queryable collection containing <see cref="Car"/> entities for the OData WebService.</para>
        /// </summary>
        public IQueryable<Car> Cars{ get { return CreateQuery<Car>(); } }

        #endregion

        #region ODataContext Implementation

        /// <summary>
        /// <para>This function creates the correct repository implementation to handle the requests
        /// for the specified Entity of the OData API.</para>
        /// <para>Because the entire concept of OData relies on 'convention over configuration', this principle is also
        /// applied to this function. When the fullType name is specified, it will be used to construct the full type 
        /// name of the matching repository. That's why repositories always need to be named 'TypeRepository'.</para>
        /// </summary>
        /// <param name="fullTypeName">The fully qualified name of the Entity who's repository is required.</param>
        /// <returns>The repository implementation for the specified Entity.</returns>
        public override object RepositoryFor(string fullTypeName)
        {
            string typeName = fullTypeName.Replace("[]", string.Empty).Substring(fullTypeName.LastIndexOf('.') + 1);
            Type repoType = Type.GetType(string.Format("My.Demo.Namespace.{0}Repository", typeName));
            if(repoType == null) throw new NotSupportedException(@"The specified type is not an Entity inside the OData API");
            return Activator.CreateInstance(repoType);
        }

        #endregion
    }


Back to index Documentation

Last edited Oct 13, 2011 at 3:00 PM by Airslash, version 2

Comments

No comments yet.