You are currently browsing the monthly archive for August 2011.

I’ve recently started working with the OData format and specifically Microsoft’s implementation of OData which is WCF Data Services, formerly known as ADO.NET Data Services and formerly formerly known as Astoria. From a high level point of view, to return or expose data in OData format we need to create objects that implement the IQueryable interface. The idea is to have the WCF service expose these objects to the calling consumer.

For this example I’m using VS Web Developer Express 2010 where I have a very simple WCF Data Service hosted in a console app (thanks to http://www.bizcoder.com). It’s returning an IQuerable collection of a simple ‘Study’ class from a repository (located in a separated dll project), which will eventually retrieve ‘Study’ classes from a db project in a third dll – for this demo the repository is dummying up the data.

The Study class has some normal properties such as Id, Name, etc and also a child class called ‘Page’ implemented as a virtual IQueryable collection. To get the code below up and running

– create a standard dll project in Visual Studio called MyStudyService, and set the output type to Console app in the project properties.

– add a second project of type class library to the solution and call it MyStudyRepository

– add a third and final project of type class library to the solution and call it MyStudyDB

Set the console app containing the service project as the startup project. This will expose the ‘Study’ data and associated ‘Page’ items. To retrieve data from the service (or from any public OData service for that matter) we can use a great piece of software called LinqPad written by Joseph Albahari. Not only will this piece of kit query OData sources, it will also query standard databases and run free-form C# expressions and statements into the bargain..all for free. You can also query the data by typing the url specified in the service in a browser:

http://localhost:123/Studies

To get the first Study object in the collection:

http://localhost:998/Studies(1)

To get the Page object of the first Study object:

http://localhost:998/Studies(1)/Pages

So now for the code – here’s the simple service that’s hosted in a console app:


using MyStudyRepository;
using MyStudyDB;

namespace MyStudyService
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string serviceAddress = "http://localhost:123";
            Uri[] uriArray = { new Uri(serviceAddress) };
            Type serviceType = typeof(StudyDataService);

            using (var host = new DataServiceHost(serviceType,uriArray))
            {
                host.Open();
                Console.WriteLine("Press any key to stop service");
                Console.ReadKey();
            }
        }
    }

    public class StudyDataService : DataService<StudyRepository>
    {
        public static void InitializeService(IDataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
        }
    }
}

Here’s the repository:


using MyStudyDB;
using MyStudyDB.Entities;

namespace MyStudyRepository
{
    public class StudyRepository : IRepository<Study>
    {
        List<Study> _listStudies = new List<Study>();
        List<Page> _listPages = new List<Page>();

        //Add data to populate myStudies list on creation of class
        public StudyRepository()
        {
            CreateStudies();
        }

        public IQueryable<Page> Pages
        {
            get
            {
                return _listPages.AsQueryable<Page>();
            }
        }

        public IQueryable<Study> Studies
        {
            get
            {
                return _listStudies.AsQueryable<Study>();
            }
        }

        public Study GetById(int itemId)
        {
            return _listStudies.SingleOrDefault(s => s.ID == itemId);
        }

        public Study GetByName(string itemName)
        {
            return _listStudies.FirstOrDefault(s => s.StudyName == itemName);
        }

        public void Add(Study item)
        {
            throw new NotImplementedException();
        }

        public void Update(Study item)
        {
            throw new NotImplementedException();
        }

        public void Delete(int itemId)
        {
            throw new NotImplementedException();
        }

        public IList<Study> List()
        {
            throw new NotImplementedException();
        }

        private void CreateStudies()
        {
            for (int i = 1; i < 5; i++)
            {
                Study myStudy = new Study()
                {
                    ID = i,
                    StudyOwnerId = i,
                    StudyName = "Study" + i.ToString(),
                    Pages = new List<Page>() {
                        new Page()
                        {
                            ID = i,
                            Name = "Page " + i.ToString(),
                            StudyId = i
                        }
                    }.AsQueryable()
                };

                myStudy.Pages.First().Study = myStudy;
                _listStudies.Add(myStudy);
            }
        }
    }
}

And finally here’s the model:

namespace MyStudyDB.Entities
{
    public class Study : IStudy
    {
        public int ID { get; set;}
        public int StudyOwnerId { get; set; }
        public string StudyName { get; set; }
        public virtual IQueryable<Page> Pages { get; set; }
    }

    public class Page : IPage
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int StudyId { get; set; }
        public virtual Study Study { get; set; }
    }
}
%d bloggers like this: