„Dieser Blog Post ist Teil der Serie „Cloud Computing mit Windows Azure“, alle bisher erschienenen Artikel finden Sie im ersten Posting der Serie!“
Dies ist nun der Folgepost zu der Windows Azure Storage Einführung, welche ich bereits letzte Woche geschrieben habe. Nun wollen wir eine kleine Anwendung mithilfe des Table Storages und des Blob Storages schreiben. Hierfür erstellen wir uns eine Fotoalbum-Engine. Damit wir los legen können brauchen wir zu allererst ein neues Windows Azure Projekt. Hier fügen wir eine ASP.NET Rolle ein. Nun sind 2 Projekte im Explorer zu erkennen:
Das erste Projekt (idealerweise mit dem Namen “PictureAlbum”) ist hierbei für die Service Einstellungen und die Service Definitionen zuständig. Das zweite Projekt ist die eigentliche Website. Hierbei gibt es jedoch zusätzlich noch die WebRole.cs. diese werden wir in einem späteren Post noch ansehen. Zu beginn benötigen wir gleich mal die WebRole1 im Ordner “Roles”. Dieser Ordner befindet sich im Projekt “CloudService1”. Da wir mit der lokalen Datenbank arbeiten wollen, müssen wir hier einige Einstellungen treffen. Durch Rechtsklick auf “WebRole1” können wir hierbei zu den Einstellungen gelangen. Hier wählen wir den Tag “Settings” aus und erstellen ein neues “Setting”. Dieses bezeichnen wir nun mit dem Namen “DevStore” und geben als Typ “Connection String” an. Nun müssen wir nur noch auf den neu erscheinenden Button klicken und die Standardeinstellung bestätigen. Damit ist die Development Storage verwendbar. Dies ist in Abbildung 2 und 3 ersichtlich.


Wenn dies erfolgreich durchgeführt wurde, können wir uns an die Erstellung der Entitäten machen. Eine Entität stellt hierbei eine einzelne Zeile in der Datenbank dar. Zu beginn wollen wir uns eine Entität für die Fotoalben erstellen. Entitäten erben stets von “TableServiceEntity”. Wir erstellen 2 Konstruktoren. Der erste, welche keine Paramter hat ruft den 2. Konstruktor auf. Dieser hat als Parameter den partitonKey und den rowKey. Beide Werte sorgen dafür das der Datensatz eindeutig ist. Wenn keine Daten geben sind, verwenden wir das Datum als PartionKey (man könnte auch eine Guid oder eine Kombination aus Guid und Datum verwenden). Jedoch soll die Partitionierung eher zusammenhängend sein. Dies erreichen wir durch das Datum. Als Rowkey verwenden wir einen Guid. Nun werden auch noch zwei Eigenschaften benötigt. Diese sind der Name des Albums und dessen Beschreibung.
public class FotoalbumEntity : TableServiceEntity
{
public FotoalbumEntity()
: this(DateTime.Now.ToShortDateString(), Guid.NewGuid().ToString())
{
}
public FotoalbumEntity(string partitionKey, string rowKey)
: base(partitionKey, rowKey)
{
}
public string AlbumName { get; set; }
public string AlbumDescription { get; set; }
}
Nun wollen wir eine weitere Entität für die Bilder erstellen. Hier werden sämtliche Bilder angegeben, welche einem Album zugeordnet sind. Es wäre an sich nicht notwendig, die Bilder einzeln anzugeben da man über Blobs Metadaten verwenden kann. Jedoch wollen wir in diesem Beispiel vorerst die Tabellen für alles verwenden. Im ImageEntity brauchen nun das Album, den Namen des Fotos, die Beschreibung und den Link dafür. HINWEIS: Die “Verlinkung” auf das Album könnte man sich an sich auch sparen indem man als PartitionKey das den RowKey des Albums verwendet
public class ImageEntity : TableServiceEntity
{
public ImageEntity()
: this(DateTime.Now.ToShortDateString(), Guid.NewGuid().ToString())
{
}
public ImageEntity(string partitionKey, string rowKey)
: base(partitionKey, rowKey)
{
}
public string Album { get; set; }
public string FotoName { get; set; }
public string Description { get; set; }
public string Link { get; set; }
}
Nun wollen wir den Datenkontext entwickeln. Hierfür benötigen wir zu erst den Verweis auf “System.Data.Services.Client”.

Im TableServiceContext werden unter anderem die Queries erstellt. Die Klasse “ImagesContext” (diese ist für die einzelnen Images zuständig) erbt hierbei von “TableServiceContext”. Im Konstruktor übergeben wir die Adresse des Storage Accounts und die Storage Credentials an die Basisklasse. Ferner benötigen wir auch noch eine Bezeichnung für unsere Tabelle. Hierbei verwenden wir “Pictures”. Um LinQ-Abfragen auf die Bilder durchführen zu können, erstellen wir einen Getter auf die Images. Dieser ist vom Typ “IQueryable<ImageEntity>” und ruft die Funktion “CreateQuery” auf. Ferner wird auch noch ein statischer getter auf den Tabellennamen benötigt.
public class ImagesContext : TableServiceContext
{
private const string tableName = "Pictures";
public ImagesContext(string baseAdress, StorageCredentials credentials)
: base(baseAdress, credentials)
{
}
public IQueryable<ImageEntity> Fotos
{
get
{
return CreateQuery<ImageEntity>(tableName);
}
}
public static string TableName
{
get
{
return tableName;
}
}
}
Und genau das selbe führen wir nun auch für den FotoalbumContext aus. Hierbei wird das jedoch auf “Albums” ausgeführt.
public class FotoalbumContext : TableServiceContext
{
private const string tableName = "Albums";
public FotoalbumContext(string baseAdress, StorageCredentials credentials)
: base(baseAdress, credentials)
{
}
public IQueryable<FotoalbumEntity> Albums
{
get
{
return CreateQuery<FotoalbumEntity>(tableName);
}
}
public static string TableName
{
get
{
return tableName;
}
}
}
Im nächsten Post werden wir dann eine Datenquelle erstellen, welche wir auch in ASP.NET einfach verwenden können.

Mario Meir-Huber
Web: www.meirhuber.de
Twitter: www.twitter.com/mario_mh