This article is based on Azure in Action,published on October, 2010. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]
Developing with the Table Service
Introduction
One of the major issues with traditional SQL Server–based databases is that individual tables can grow too large, slowing down all operations against the table. Although the Windows Azure Table service is highly efficient, storing too much data in a single table can still degrade data access performance.
The Table service allows you to specify how your table could be split into smaller partitions by requiring each entity to contain a partition key. The Table service can then scale out by storing different partitions of data on separate physical servers. Any entities with the same partition key must reside together on the same physical server.
We will develop a web application to use the Table service. This application will manage our Hawaiian shirt inventory for our fictitious store website.
Creating a project
Create a new Cloud Service web role project called ShirtManagement. Open Visual Studio and select File > New > Project. Visual Studio displays a list of available templates; select the Cloud Service template group, and then select Windows Azure Cloud Service in the menu. Name the project and click OK. A pop-up menu opens in which you pick the project types you want to add to your Azure solution. Because you’re building a simple website, without any backend processing, choose the ASP.NET Web Role template. After you add the web role to the project, you can rename it; then click OK. You’ll see the New Cloud Service Project window with one solution, as shown in figure 1.
Figure 1 Creating a new Azure Application project is easy. Just add the different roles you’ll need in your solutionAs with the other storage services, communication with the Table service occurs through the REST API. Although you can use this API directly, you’re likely to be more productive using the StorageClient library provided in the Windows Azure SDK.
Whenever you create a new Cloud Service project, this library will automatically be referenced. But if you’re building a brand new class library or migrating an existing project, you can reference the following storage client assembly manually:
- Microsoft.WindowsAzure.StorageClient
In addition, you’ll need to reference the ADO.NET Data Services assemblies:
- System.Data.Services
- System.Data.Services.Client
ADO.NET Data Services
The Table service exposes its HTTP REST APIs through its implementation of the ADO.NET Data Services framework. The use of this framework means we can utilize the ADO.NET Data Services client assemblies to communicate with the service rather than having to develop or use a custom REST wrapper.
Because ADO.NET Data Services is used by the Storage Client SDK, you’ll need to reference those assemblies too.
Now that we’ve set up our project, let’s look at how we can add our product entity class to the project.
Defining an entity
Before we create our product-management web page, we need to create our entity in the web project. At this stage, we’ll just add our entity directly to our web page.
To keep our example simple, we’ll just store the shirt name and description. Add a new class to your web project named Product.cs and define the class as shown in listing 1.
Listing 1 Product entity
public class Product : TableServiceEntity { public string Name { get; set; } public string Description { get; set; } }
In listing 1, the Product class inherits from the TableServiceEntity base class (Microsoft.WindowsAzure.TableService.TableServiceEntity). This base class contains the three properties required by all table storage entities:
- Timestamp
- PartitionKey
- RowKey
Now that we’ve set up our project and defined our entity, we need to create a table to store our entity in. The same method can be used in both the development and live environments.
Creating a table
The simplest method of creating a table is to create a PowerShell script or to use one of the many storage clients that are available. In this chapter we’ll use Azure Storage Explorer, which you can download from CodePlex: http://azurestorageexplorer.codeplex.com/.
In this section, we’ll look at how to create a table in two ways: using Azure Storage Explorer and using code.
Creating a table using the Azure Storage Explorer
Once you have downloaded and fired up Azure Storage Explorer, it will automatically connect you to your development storage account as long as your local development storage service is running.
To create a new table in your storage account, all you need to is select Table > New Table and enter the name of your table (Product, in this case). Figure 2 shows our newly created Product table in Azure Storage Explorer.
Figure 2 The Azure Storage Explorer showing our newly created Product tableAlthough using a tool such as Azure Storage Explorer is probably the easiest method of creating a new table, you may wish to do this manually in C#.
Creating a table in code
In this example, we’ll manually create a console application that will create a new table in our storage account when it’s run. Although we’ll use a console application in this example, we could easily use a web application, Windows Forms application, or Windows Presentation Foundation application. The deployment application doesn’t need to be a cloud application (web or worker role); it can be a standard application that you run locally.
To create the application, perform the following steps:
- Create a console application targeting .NET 3.5.
- Add a reference to System.Data.Services.
- Add a reference to System.Data.Services.Client.
- Add a reference to Microsoft.WindowsAzure.StorageClient.
- Add an app.config or web.config entry with your storage account credentials.
- Add the following code to create the table:
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) => { configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)); }); var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString"); CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); tableClient.CreateTableIfNotExist("Product");
The code added in step 6 retrieves storage account information from the app.config and then calls the CreateTableIfNotExist method from the CloudTableClient object, passing in the name of the table to create (Product).
Deploying to live
The code used to create a new table won’t only work on your development storage account but will also work against the live system. All you need to do to make this code work against the live system is to change the DataConnectionString configuration setting to your live account.
Now that we know how to create our table both in the live system and in development storage, it’s worth taking a quick peek at how this is implemented in the development storage backing store. Figure 3 shows how tables are represented in the development storage SQL Server database.
Figure 3 How tables are represented in the development storage SQL Server databaseAs we can see in figure 3, the SQL Server database that stores our entities is pretty flexible. The TableContainer table keeps a list of all the tables stored in our development storage account. Because we can create tables dynamically, any new table created will contain a new entry in this table.
Each row in the TableRow table in figure 3 stores a serialized version of our entity. As you can see from this table definition, the only fixed data that’s stored in this table are AccountName, TableName, PartitionKey, RowKey, and TimeStamp. All other properties are stored in the Data column. As you can see, the actual development storage schema relates to the logical representation that we can see in table 1.
Summary
The Table service provides massively scalable storage and it differs from traditional relational databases, such as SQL Server. The Table service is a scalable way of storing and querying entities. We can sometimes assume we need relational databases when there are other ways of representing data in our solution. Designing systems is all about tradeoffs, and the tradeoff with relational databases is scalability. By using the Table service, you gain scalability, but the cost is that you have to think and design systems in a different way.