The World’s Leading Microsoft .NET Magazine
   
 
The .NET Addict's Blog

My Top Tags

                                                           

My RSS Feeds








I heart FeedBurner

Latest Diggs - Programming

Computers Blogs - Blog Top Sites

Site Hits

Total: 4,868,426
since: 19 Jan 2005

Working with Table Storage on the Windows Azure November 2009 CTP

posted Sun 15 Nov 09

If you've been working with Azure for a while then you've probably spent some time using the StorageClient sample that came with previous versions of the SDK. With the November 2009 release of the SDK (the one they'll be using at PDC 2009), they have wrapped that sample up into the SDK and refactored it to fit more in line with the conventions and quality standards of a Microsoft API. As a result, some of your code will break (but not much). Queue storage and Blob storage (discussed in upcoming posts) actually have more breaking changes than table storage.

Table storage, under the hood, is exposed as an ADO.NET Data Service (formerly Astoria). As a result, if you've used the System.Data.Services.Client library before, you've already got a leg up in interacting with Azure Storage.

When you're working with table storage, there are a few things that you're going to need. Once you've got these, you're good to go:

  • References to System.Data.Services.Client and Microsoft.WindowsAzure.StorageClient (obviously you also need a reference to service runtime if you're hitting table storage from within the cloud itself... remember that you can hit table storage from the desktop too, e.g. from WPF applications).
  • Credentials. There have been some changes to the way storage client credentials work that are beyond the scope of this post, but you can still use the same accountname/account shared key pattern that you used in the past.
  • A DataServiceContext. You're going to need this to interact with the tables in table storage. As you'll see in the code below, the pattern is to create your own context that derives from the base and exposes your tables as IQueryables. If you've ever worked with ADO.NET Data Services or Entity Framework before, this pattern should also look familiar.
  • Entity objects. Every table that you have in table storage contains arbitrary columns. In other words, if you really wanted, you could have a different schema for every row in your table. However, to work with it using the Data Services client, each row needs to conform to a fixed schema - this fixed schema you'll represent with a regular C# class that contains the necessary partition key and row key properties. This class also needs a parameterless constructor (required by the data services client to reconstitute instances of that class from the HTTP results)
  • The cloud table client. This new class will let you create tables and test for the existence of tables. You do not need to use this class for querying table storage, it's more of an administrative class for dealing with table storage itself.   

The first thing we're going to want to do is get the credentials. The new SDK allows us to dynamically determine if we're running in a fabric or running as a standalone app (which allows us to build apps that we can run on-premise OR in the cloud!). Here's some code I used to get the configuration settings for the account name and shared key:

string accountKey = ConfigurationManager.AppSettings["AccountSharedKey"];
string tableBaseUri = ConfigurationManager.AppSettings["TableStorageEndpoint"];
if (RoleEnvironment.IsAvailable)
{
   accountName =
RoleEnvironment.GetConfigurationSettingValue("AccountName");
   accountKey =
RoleEnvironment.GetConfigurationSettingValue("AccountSharedKey");
}

Once you've got the account key and the account name, you can get an instance of the storage credentials and table client classes:

StorageCredentialsAccountAndKey creds =
   
new StorageCredentialsAccountAndKey(accountName, accountKey);
CloudTableClient tableStorage = new CloudTableClient(tableBaseUri, creds);
CustomerContext ctx = new CustomerContext(tableBaseUri, creds);

Using the table storage class, we can create a new table (if it doesn't already exist):

if (tableStorage.CreateTableIfNotExist("Customers"))
{
CustomerRow cust = new CustomerRow("AccountsReceivable", "kevin");
cust.FirstName =
"Kevin";
cust.LastName =
"Hoffman";
ctx.AddObject(
"Customers", cust);
ctx.SaveChanges();
}
 

Here I'm also using my customer context class and my customer row class (will show those shortly) in order to put a new customer into table storage. Note my use of an application name for the partition key and the username for the row key. Entire chapters of books can (and will) be written on strategies and patterns for using partition and row keys.

Now let's say that we're inside an MVC 2 controller and we want to make the list of customers available to the view. If we're not doing a strongly typed view (which we should be doing unless we can't help it...) then we can use code that looks like this:

CustomerRow[] customers = ctx.Customers.ToArray();
ViewData[
"Customers"] = customers;

Now let's look at the CustomerContext class:

public class CustomerContext : TableServiceContext
{
   
public CustomerContext(string uri, StorageCredentials creds) : base(uri, creds) { }
   
public IQueryable<CustomerRow> Customers
    {
       
get
       
{
           
return this.CreateQuery<CustomerRow>("Customers");
        }
    }
}

The CustomerRow class is just a POCO class that has a default constructor and a constructor that takes a partition key and a row key, and inherits from the TableServiceEntity class.

public class CustomerRow : TableServiceEntity
{
   
private string firstName;
   
private string lastName;
   
private string userName;
   
private string applicationName;

   
public CustomerRow(string applicationName, string userName)
      :
base(applicationName, userName)
    {
      ApplicationName = applicationName;
      UserName = userName;
    }

    public CustomerRow() : base() { }

I snipped out the rest of the class for brevity - I'm assuming we've all seen stock property accessors before. At this point you should be ready to roll using table storage. There is also one other benefit they gave us in November 2009 CTP - you no longer need to pre-rig your database schema in your SQL 2008 database!! The new development storage simulator accurately simulates the dynamic schema nature of the actual table storage in the cloud. I can't begin to describe how many headaches this alleviates.

Enjoy table storage on the new Nov 2009 CTP and I'll be posting similar blog posts about the new Queue storage and Blob storage clients shortly!

tags:            

links: digg this    del.icio.us    technorati    reddit

AddThis Social Bookmark Button




1. be789 left...
Sun 15 Nov 09 7:43 pm

Thanks for your post. One question: what AccountName is used for the local development storage?


2. Kevin Hoffman left...
Sun 15 Nov 09 7:44 pm

You use the same account name and key that you used in previous versions of azure. The account name is 'devstoreaccount1' and the shared key is Eby8vdM 02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBekso GMGw==


3. be789 left...
Sun 15 Nov 09 8:22 pm

So if running locally, you use ConfigurationManager.AppSettings and if running in the cluod you use RoleEnvironment.GetConfigurationSettingValue("AccountName")?


4. Kevin Hoffman left...
Sun 15 Nov 09 8:27 pm

It's fuzzy if you say "local" ... Really the way I like to think of it as in-cloud and on-premise. Running in-cloud (which can include running in the local development fabric) you're going to get your configuration settings from the RoleEnvironment. Running on-premise you're going to use the standard mechanism of using ConfigurationManager. This type of logic can easily be abstracted (and is abstracted in many of the samples in the SDK) so you only have to write that kind of logic once.


5. be789 left...
Sun 15 Nov 09 9:28 pm

Now I see why I was confused. I was mixing up your use of "on-premise" with mine. I was talking about an Azure app running against the local dev store. Anyhow, thanks again for your post.


6. Beachley left...
Wed 25 Nov 09 3:28 pm :: http://eTrainingJournal.com

Thank you Kevin !!! Your post saved me alot of time. My website http://etj.me has about 6 different Azure tables each with their own TableServiceContext and TableServiceEntity - for a couple hours I thought this would be a real chore, but your post has the essential facts clearly laid out. Another helpful thing is for folks who have been usiing AspProviders to pick up an updated version at http://code.msdn.microsoft.com/windowsazuresamples/Relea se/ProjectReleases.aspx?ReleaseId=3526. This is the Windows Azure Additional Samples for the November release.


Tag Related Posts

How to Build your First Azure-Powered MVC App

Tue 29 Sep 09 2:16 P GMT-05
tags:        

Configuration Settings in Azure Applications

Mon 28 Sep 09 2:59 P GMT-05
tags:        

Velocity CTP3 coming up next week

Thu 12 Mar 09 4:44 P GMT-05
tags:            

SSDS loses an "S" and gains some awesome

Wed 11 Mar 09 11:42 A GMT-05
tags:              

Live Mesh Tutorial 1 - Hello Live Mesh

Thu 06 Nov 08 2:33 P GMT-05

Microsoft Windows Azure Distilled

Tue 28 Oct 08 1:42 P GMT-05

The Evolution of the Cloud - Then and Now

Mon 06 Oct 08 12:34 P GMT-05

Microsoft's Lofty Direction

Sun 05 Oct 08 2:30 P GMT-05

MobileMe vs. Live Mesh Throwdown - Round 1

Wed 16 Jul 08 10:33 A GMT-05

Acropolis or Acrapolis?

Thu 05 Jul 07 12:34 P GMT-05
tags:      

Visual Studio "Orcas" - March CTP is Available

Wed 28 Feb 07 12:28 P GMT-05
tags:            

July CTP is out... yay.

Tue 18 Jul 06 6:34 P GMT-05
tags: