
Generating Database Tables in Development Storage
An additional tool, the DevTableGen.exe tool, generates tables for use with the local Table service from a list of managed assemblies. You can use this tool to generate the tables that you need in order to test your service. For usage information for DevTableGen.exe, see DevTableGen Command-Line Tool.
The steps you must take to generate a database and tables in order to use the local Table service are as follows:
-
Within your client code, define classes that model the schema used by your tables. To design your classes, you'll need to use the .NET Client Library for ADO.NET Data Services. The client library provides the DataServiceContext class as part of the System.Data.Services.Client assembly.
-
Run the DevTableGen tool on your compiled assemblies to generate the SQL database.
-
Run development storage and select the database that you have generated as the source for the Table service.
-
If you modify your schema, recompile the assemblies and regenerate the database with the DevTableGen tool with the /forceCreate option.
To call DevTableGen.exe, you must have privileges to create database tables in the SQL Server Express installation. Creating tables requires that you are a member of the sysadmin or dbcreator server roles defined for SQL Server Express.
To generate a database table for use with development storage, construct a class that models the desired schema. The DevTableGen tool reflects over the given set of assemblies for properties of type IQueryable<C> on classes derived from the DataServiceContext class, where C is the class that models your table schema. The class C (or a base class of C) must specify the [DataServiceKey("PartitionKey", "RowKey")] attribute. The DevTableGen tool creates a table with a schema corresponding to the properties defined for class C.
The following code example is derived from the StorageClient Sample. The sample defines a class named SampleDataServiceContext that inherits from DataServiceContext. This class includes a property of type IQueryable<SampleEntity>. This property determines the name for the table. The SampleEntity class defines properties for an entity (which is similar to a row in a table). SampleEntity derives from the TableStorageEntity class, a base class which includes the properties PartitionKey and RowKey. These properties are required for every table in the Table service.
public class SampleEntity : TableStorageEntity
{
public SampleEntity(string partitionKey, string rowKey)
: base(partitionKey, rowKey)
{
C = TableStorageConstants.MinSupportedDateTime;
}
public SampleEntity() : base() {
}
public int A {
get;
set;
}
public string B {
get;
set;
}
public DateTime C {
get;
set;
}
public Guid D
{
get;
set;
}
}
internal class SampleDataServiceContext : TableStorageDataServiceContext
{
internal SampleDataServiceContext(StorageAccountInfo accountInfo)
: base(accountInfo)
{
}
internal const string SampleTableName = "SampleTable";
public IQueryable<SampleEntity> SampleTable
{
get
{
return this.CreateQuery<SampleEntity>(SampleTableName);
}
}
}
The following code example gives the definition for the TableStorageEntity class from which the SampleEntity class derives. Note that it includes the [DataServiceKey("PartitionKey", "RowKey")] attribute.
[CLSCompliant(false)]
[DataServiceKey("PartitionKey", "RowKey")]
public abstract class TableStorageEntity
{
public DateTime Timestamp
{
get;
set;
}
public virtual string PartitionKey
{
get;
set;
}
public virtual string RowKey
{
get;
set;
}
protected TableStorageEntity(string partitionKey, string rowKey)
{
PartitionKey = partitionKey;
RowKey = rowKey;
}
protected TableStorageEntity()
{
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
TableStorageEntity rhs = obj as TableStorageEntity;
if (rhs == null)
{
return false;
}
return (this.PartitionKey == rhs.PartitionKey
&& this.RowKey == rhs.RowKey);
}
public override int GetHashCode()
{
if (PartitionKey == null)
{
return base.GetHashCode();
}
if (!String.IsNullOrEmpty(this.RowKey))
{
return this.PartitionKey.GetHashCode() ^ this.RowKey.GetHashCode();
}
else
{
return this.PartitionKey.GetHashCode();
}
}
}
The DevTableGen tool performs some validation in the process of creating tables. For example, if your assembly defines a property of a type that is not supported in The Table service, such as a Decimal type or a reference type, DevTableGen returns an error.
If you modify the schema as modeled by your assembly, you will need to run DevTableGen again to update the tables in development storage.