|
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:
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 : TableServiceEntitypublic 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!
Thanks for your post. One question: what AccountName is used for the local
development storage?
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==
So if running locally, you use ConfigurationManager.AppSettings and if
running in the cluod you use
RoleEnvironment.GetConfigurationSettingValue("AccountName")?
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.
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.
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.