At TechEd I got a lot of questions about how to expose Data as OData
By now you probably know you can use Data Services and the Entity Framework to expose data from a database as an OData Service. You might even know you can use Data Services with a custom Data Service Provider to expose arbitrary data from anywhere.
But did you know about the Data Services Reflection provider?.
Turns out reflection provider is VERY simple to use.
To show you just how simple I am going to create an odata service to expose some in memory data.
First you need some data, so how about this topical data:
[EntityPropertyMapping("Name", SyndicationItemProperty.Title, SyndicationTextContentKind.Plaintext, false)][EntityPropertyMapping("Odds", SyndicationItemProperty.Summary, SyndicationTextContentKind.Plaintext, false)]public class Team { public static List<Team> Teams = new List<Team>{ new Team {ID = 1, Name = "New Zealand", Odds = "1:1000"}, new Team {ID = 2, Name = "Paraquay", Odds = "1:50"}, … }; public int ID{get;set;} public string Name {get;set;} public string Odds { get; set; }}[DataServiceKey("Name")][EntityPropertyMapping("Name", SyndicationItemProperty.Title, SyndicationTextContentKind.Plaintext, false)]public class Group{ public static List<Group> Groups = new List<Group>{ new Group { Name = "A", Teams = new List<Team>{ Team.Teams[0], Team.Teams[1], Team.Teams[2], Team.Teams[3] } }, new Group { Name = "B", Teams = new List<Team>{ Team.Teams[4], Team.Teams[5], Team.Teams[6], Team.Teams[7] } }, … }; public string Name {get;set;} public List<Team> Teams {get;set;}}
[EntityPropertyMapping("Name", SyndicationItemProperty.Title, SyndicationTextContentKind.Plaintext, false)][EntityPropertyMapping("Odds", SyndicationItemProperty.Summary, SyndicationTextContentKind.Plaintext, false)]public class Team { public static List<Team> Teams = new List<Team>{ new Team {ID = 1, Name = "New Zealand", Odds = "1:1000"}, new Team {ID = 2, Name = "Paraquay", Odds = "1:50"}, … };
public int ID{get;set;} public string Name {get;set;} public string Odds { get; set; }}
[DataServiceKey("Name")][EntityPropertyMapping("Name", SyndicationItemProperty.Title, SyndicationTextContentKind.Plaintext, false)]public class Group{ public static List<Group> Groups = new List<Group>{ new Group { Name = "A", Teams = new List<Team>{ Team.Teams[0], Team.Teams[1], Team.Teams[2], Team.Teams[3] } }, new Group { Name = "B", Teams = new List<Team>{ Team.Teams[4], Team.Teams[5], Team.Teams[6], Team.Teams[7] } }, … }; public string Name {get;set;} public List<Team> Teams {get;set;}}
Notice the use of the [DataServiceKey] and [EntityPropertyMapping] attributes:
Next you need a class to act as your Data Source. Data Services will expose all the IQueryable properties as Feeds and infer types for all the types exposed by those Feeds.
So if I want two feeds, to expose Groups and Teams from the world cup, I’d do it like this:
public class WorldCupData{ public IQueryable<Team> Teams{ get{ return Team.Teams.AsQueryable(); } } public IQueryable<Group> Groups{ get{ return Group.Groups.AsQueryable(); } }}
Now all you need to do is create the Data Service, and expose our sets. Simply add a WCF Data Service to you web application and modify the generated code to look like this:
public class WorldCup : DataService<WorldCupData>{ // This method is called only once to initialize service-wide policies. public static void InitializeService(DataServiceConfiguration config) { config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); config.SetEntitySetPageSize("*", 100); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; }}
That’s it you are done:
A couple of points worth noting:
Enjoy.