This walkthrough shows how a simple web application can be built using the reference data caching features in the “Microsoft WCF Data Services For .NET March 2011 Community Technical Preview with Reference Data Caching Extensions” aka “Reference Data Caching CTP”. The walkthrough isn’t intended for production use but should be of value in learning about the caching protocol additions to OData as well as to provide practical knowledge in how to build applications using the new protocol features.
The walkthrough contains five sections as follows:
The pre-requisites and setup requirements for the walkthrough are:
Next you’ll create an ASP.NET Web Application where the OData service and HTML5 front end will be hosted.
In order to build a Data Service we need a data model and data to expose. You will use Entity Framework Code First classes to define the delta enabled model and a Code First database initializer to ensure there is seed data in the database. When the application runs, EF Code First will create a database with appropriate structures and seed data for your delta-enabled service.
public class Session { public int Id { get; set; } public string Name { get; set; } public DateTime When { get; set; } public ICollection<Tweet> Tweets { get; set; } } [DeltaEnabled] public class Tweet { [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] [Column(Order = 1)] public int Id { get; set; } [Key] [Column(Order = 2)] public int SessionId { get; set; } public string Text { get; set; } [ForeignKey("SessionId")] public Session Session { get; set; } } Note the attributes used to further configure the Tweet class for a composite primary key and foreign key relationship. These attributes will directly affect how Code First creates your database.
3. Add a using statement at the top of the file so the DeltaEnabled annotation will resolve:
using System.ComponentModel.DataAnnotations;
4. Add a ConferenceContext DbContext class to your model.cs file and expose Session and Tweet DbSets from it.
public class ConferenceContext : DbContext { public DbSet<Session> Sessions { get; set; } public DbSet<Tweet> Tweets { get; set; } }
5. Add a using statement at the top of the file so the DbContext and DbSet classes will resolve:
using System.Data.Entity;
6. Add seed data for sessions and tweets to the model by adding a Code First database initializer class to the model.cs file:
public class ConferenceInitializer : IncludeDeltaEnabledExtensions<ConferenceContext> { protected override void Seed(ConferenceContext context) { Session s1 = new Session() { Name = "OData Futures", When = DateTime.Now.AddDays(1) }; Session s2 = new Session() { Name = "Building practical OData applications", When = DateTime.Now.AddDays(2) }; Tweet t1 = new Tweet() { Session = s1, Text = "Wow, great session!" }; Tweet t2 = new Tweet() { Session = s2, Text = "Caching capabilities in OData and HTML5!" }; context.Sessions.Add(s1); context.Sessions.Add(s2); context.Tweets.Add(t1); context.Tweets.Add(t2); context.SaveChanges(); } }
7. Ensure the ConferenceIntializer is called whenever the Code First DbContext is used by opening the global.asax.cs file in your project and adding the following code:
void Application_Start(object sender, EventArgs e) { // Code that runs on application startup Database.SetInitializer(new ConferenceInitializer()); }
Calling the initializer will direct Code First to create your database and call the ‘Seed’ method above placing data in the database
8. Add a using statement at the top of the global.asax.cs file so the Database class will resolve:
Next you will build the delta enabled OData service. The service allows querying for data over HTTP just as any other OData service but in addition provides a “delta link” for queries over delta-enabled entities. The delta link provides a way to obtain changes made to sets of data from a given point in time. Using this functionality an application can store data locally and incrementally update it, offering improved performance, cross-session persistence, etc.
1. Add a new WCF Data Service to the Project and name it ConferenceService.
2. Remove the references to System.Data.Services and System.Data.Services.Client under the References treeview. We are using the Data Service libraries that are delta enabled instead.
3. Change the service to expose sessions and tweets from the ConferenceContext and change the protocol version to V3. This tells the OData delta enabled service to expose Sessions and Tweets from the ConferenceContext Code First model created previously.
public class ConferenceService : DataService<ConferenceContext> { // This method is called only once to initialize service-wide policies. public static void InitializeService(DataServiceConfiguration config) { config.SetEntitySetAccessRule("Sessions", EntitySetRights.All); config.SetEntitySetAccessRule("Tweets", EntitySetRights.All); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3; } }
4. Right-click on ConferenceService.svc in Solution Explorer and click “View Markup”. Change the Data Services reference as follows.
Change:
<%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Service="ConferenceReferenceDataTest.ConferenceContext" %>
To:
<%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services.Delta, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Service="ConferenceReferenceDataTest.ConferenceService" %>
6. Change the ConferenceService.svc to be the startup file for the application by right clicking on ConferenceService.svc in Solution Explorer and choosing “Set as Start Page”.
7. Run the application by pressing F5.
<link rel="http://odata.org/delta" href=http://localhost:11497/ConferenceService.svc/Tweets?$deltatoken=2002 />
The delta link is shown because the DeltaEnabled attribute was used on the Tweet class.
8. Open a new browser instance, paste the delta link into the nav bar: http://localhost:11497/ConferenceService.svc/Tweets?$deltatoken=2002, and press enter.
9. Note the delta link returns no new data. This is because no changes have been made to the data in the database since we queried the service and obtained the delta link. If any changes are made to the data (Inserts, Updates or Deletes) changes would be shown when you open the delta link.
10. Open SQL Server Management Studio, create a new query file and change the connection to the ConferenceReferenceDataTest.ConferenceContext database. Note the database was created by a code first convention based the classes in model.cs.
11. Execute the following query to add a new row to the Tweets table:
insert into Tweets (Text, SessionId) values ('test tweet', 1)
12. Refresh the delta link and note that the newly inserted test tweet record is shown. Notice also that an updated delta link is provided, giving a way to track any changes from the current point in time. This shows how the delta link can be used to obtain changed data. A client can hence use the OData protocol to query for delta-enabled entities, store them locally, and update them as desired.
13. Stop debugging the project and return to Visual Studio.
We’re going to use HTML5 and the reference data caching-enabled datajs library to build a simple front end that allows browsing sessions and viewing session detail with tweets. We’ll leverage a pre-written library that uses the reference data capabilities added to OData and leverages the datajs local store capabilities for local storage.
1. Add a new HTML page to the root of the project and name it SessionBrowsing.htm.
2. Add the following HTML to the <body> section of the .htm file:
<body> <button id='ClearDataJsStore'>Clear Local Store</button> <button id='UpdateDataJsStore'>Update Tweet Store</button> <br /> <br /> Choose a Session: <select id='sessionComboBox'> </select> <br /> <br /> <div id='SessionDetail'>No session selected.</div> </body>
3. At the top of the head section, add the following script references immediately after the head element:
<head> <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.2.min.js" type="text/javascript"></script> <script src=".\Scripts\datajs-0.0.2.js" type="text/javascript"></script> <script src=".\Scripts\TweetCaching.js" type="text/javascript"></script> …
4. In the head section, add the following javascript functions. These functions:
<script type="text/javascript"> //load all sessions through OData $(function () { //query for loading sessions from OData var sessionQuery = " ConferenceService.svc/Sessions?$select=Id,Name"; //initial load of sessions OData.read(sessionQuery, function (data, request) { $("#sessionComboBox").html(""); $("<option value='-1'></option>").appendTo("#sessionComboBox"); var i, length; for (i = 0, length = data.results.length; i < length; i++) { $("<option value='" + data.results[i].Id + "'>" + data.results[i].Name + "</option>").appendTo("#sessionComboBox"); } }, function (err) { alert("Error occurred " + err.message); } ); //handler for combo box $("#sessionComboBox").change(function () { var sessionId = $("#sessionComboBox").val(); if (sessionId > 0) { var sessionName = $("#sessionComboBox option:selected").text(); //change localStore to localStore everywhere and TweetStore to be TweetStore var localStore = datajs.createStore("TweetStore"); document.getElementById("SessionDetail").innerHTML = ""; $('#SessionDetail').append('Tweets for session ' + sessionName + ":<br>"); AppendTweetsForSessionToForm(sessionId, localStore, "SessionDetail"); } else { var detailHtml = "No session selected."; document.getElementById("SessionDetail").innerHTML = detailHtml; } }); //handler for clearing the store $("#ClearDataJsStore").click(function () { ClearStore(); }); //handler for updating the store $("#UpdateDataJsStore").click(function () { UpdateStoredTweetData(); alert("Local Store Updated!"); }); }); </script>
5. Change the startup page for the application to the SessionBrowsing.htm file by right clicking on SessionBrowsing.htm in Solution Explorer and choosing “Set as Start Page”.
6. Run the application. The application should look similar to:
This simple application uses OData delta enabled functionality in an HTML5 web application using datajs. In this case datajs local storage capabilities are used to store Tweet data and datajs OData query capabilities are used to update the Tweet data.
This walkthrough offers an introduction to how a delta enabled service and application could be built. The objective was to build a simple application in order to walk through the reference data caching features in the OData Reference Data Caching CTP. The walkthrough isn’t intended for production use but hopefully is of value in learning about the protocol additions to OData as well as in providing practical knowledge in how to build applications using the new protocol features. Hopefully you found the walkthrough useful. Please feel free to give feedback in the comments for this blog post as well as in our prerelease forums here.
I like delta-enabled! Just about makes up for OData not supporting timestamp columns.
Will this play well with Azure AppFabric Caching and multiple WebRoles?
This is amazing!
Now please put it in CRM2011 and SharePoint2011
XD