In this post we are going to use an adapted Guestbook application from the Windows Azure Training Kit. This is an excellent demo because it covers all the main topics in one demo:
Understanding A Finished Project
http://brunoblogfiles.com/zips/WhackyPhotos.zip
In this post we are going to use an adapted Guestbook application from the Windows Azure Training Kit. I wanted something more colorful and I wanted to play around with some of the code I had laying around.
Simple Projects
The projects are either class libraries or simple ASP.NET web sites. The projects below only involve 2 “File / New / Project” commands.
The reasonable next step is to discuss the data layers, since that is the most significant part of the project. The other parts of this project are absolutely trivial if you know anything about ASP.NET Web Forms.
GuestBook_Data
Most of the functionality is in these three classes that provide the functionality to access and modify data. The rest of this post will address how these 3 classes work together to provide access to our tables and blogs. Remember, tables are simple ISAM file structures that support the LINQ query language. Here are some more facts about table objects:
Table objects
Your storage account will contain 1 or more tables. Entities are like rows, but differ in the fact that they are unstructured.
Additional Key Facts- A storage account can create many tables- Table name is scoped by account- Set of entities (i.e. rows)
An Entity is a set of properties, where a property can be likened to a table column.
There are 3 required properties:
Together the RowKey and PartitionKey:
The timestamp is also required in an entity. Timestamps are:
The next screen is about our main data – the GuestBookEntry class, which represents the data that is stored in table objects.
GuestBookEntry.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.WindowsAzure.StorageClient; namespace WhackyPhotos_Data { // By inheriting from TableServiceEntity, we can // communicate with an Azure Table Entity in the cloud. // TableServiceEntity is a class found in the Storage Client API // This class defines the PartititionKey, RowKey and TimeStamp properties // These properties are required by every entity stored // in a Windows Azure table // Together, the PartitionKey and RowKey define the DataServiceKey // that uniquely identifies every entity within a table public class GuestBookEntry : Microsoft.WindowsAzure.StorageClient.TableServiceEntity { // Add a constructor public GuestBookEntry() { PartitionKey = DateTime.UtcNow.ToString("MMddyyyy"); // Row key allows sorting, so we make sure // the rows come back in time order. RowKey = string.Format("{0:10}_{1}", DateTime.MaxValue.Ticks - DateTime.Now.Ticks, Guid.NewGuid()); } // Public fields for class public string Message { get; set; } public string GuestName { get; set; } public string PhotoUrl { get; set; } public string ThumbnailUrl { get; set; } } }
The data that we wish to manage in a table object is based on a class. In this case, GuestBookEntry is a class that derives from TableServiceEntity.
Table Service Entity
What we are storing in our Table objects
Message, GuestName, PhotoUrl, ThumbnailUrl represents the data that we wish to store in the table object.
NOTE: See previous descriptions of the significance of PartitionKey and RowKey.
In order for our data to be available via a REST-ful interface
GuestBookDataContext.cs
class GuestBookDataContext : TableServiceContext { public GuestBookDataContext(string baseAddress, StorageCredentials credentials) : base(baseAddress, credentials) { } public IQueryable<GuestBookEntry> GuestBookEntry { get { return this.CreateQuery<GuestBookEntry>("GuestBookEntry"); } } }
GuestBookEntryDataSource.cs
public class GuestBookEntryDataSource { // This class represent the storage account and // the data context private static CloudStorageAccount storageAccount; private GuestBookDataContext context; public GuestBookEntryDataSource() { this.context = new GuestBookDataContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); this.context.RetryPolicy = RetryPolicies.Retry(3, TimeSpan.FromSeconds(1)); } static GuestBookEntryDataSource() { //Initialize storage account. Use settings from // configuration. //Use CreateTablesFromModel to create // tables based on GuestBookDataContext. storageAccount = CloudStorageAccount.FromConfigurationSetting( "DataConnectionString"); CloudTableClient.CreateTablesFromModel( typeof(GuestBookDataContext), storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); } public IEnumerable<GuestBookEntry> Select() { var results = from g in this.context.GuestBookEntry where g.PartitionKey == DateTime.UtcNow.ToString("MMddyyyy") select g; return results; } public void AddGuestBookEntry(GuestBookEntry newItem) { this.context.AddObject("GuestBookEntry", newItem); this.context.SaveChanges(); } public void UpdateImageThumbnail(string partitionKey, string rowKey, string thumbUrl) { var results = from g in this.context.GuestBookEntry where g.PartitionKey == partitionKey && g.RowKey == rowKey select g; var entry = results.FirstOrDefault<GuestBookEntry>(); entry.ThumbnailUrl = thumbUrl; this.context.UpdateObject(entry); this.context.SaveChanges(); } }
The final architectural discussion will be about the Developer fabric, which is essentially a simulation environment for the cloud on your local machine.
The Developer Fabric
When you run your project you will be able to go to the system tray to see the developer fabric.
The development fabric simulates the Windows® Azure™ fabric on your local computer so that you can run and test your service locally before deploying it. The development fabric allows you to debug and fine-tune the behavior of your service before it is deployed. It provides a user interface for observing and managing local service deployments.
Showing the Development Fabric and the Development Storage
Note we have just one instance of our web role instantiated
Note the “Service Details”
Details about our Development Storage
Summary
I hope that gives you a high level view of the architecture of a well-rounded Azure application that leverages all the great features of Azure. We discussed and illustrated: