在【Azure Services Platform Step by Step-第9篇】Windows Azure Storage概覽中,我們已經討論過Table Storage的作用和特點。本篇將以搭建簡單的聊天室為例,示範如果使用最簡單的代碼,將C#實體類(Entity)直接存入Table Storage中,徹底告別SQL Server 200x和ORM工具。
最終效果: (已部署到雲端的Demo :http://ibm.cloudapp.net/ChatMain.aspx)
首先讓我們一起回顧一下Table Storage的結構。
每行都是一個獨立的Entity。
Partition Key和RowKey起到了類似於主鍵的作用,它們用來標識Entity,同時也可以在實際使用中作為分類查詢條件。
TimeStamp屬性(沒畫出)是每行都預設有的,它自動記錄該行資料最後更新的時間。
接下來我們來看看StorageClient中是怎樣使用TableStorage的
看著這圖,單看檔案名稱,覺得很奇怪吧? Blob和Queue都使用了Rest來實現,唯獨Table沒有一個對應REST的類。那它是怎麼做的呢?
查看原始碼可以發現,原來,它使用的是System.Data.Services.Client裡的DataServiceQuery和DataServiceContext這兩個ADO.NET 資料服務的關鍵類來實現的。拿TableStorageDataServiceContext類來說,它繼承自DataServiceContext,或者說,它把DataServiceContext封裝成了Azure版!
(對ADO.NET資料服務Client不瞭解的朋友請查閱http://msdn.microsoft.com/zh-cn/library/system.data.services.client.dataservicecontext.aspx)
呵呵,不管怎麼樣,我們使用方便就好了。
瞭解完了原理,我們來進入正題吧。
第一步:
在VS008中建立Web Cloud Service、配置ServiceConfiguration.cscfg、ServiceDefinition.csdef ,添加對StorageClient項目的引用。這裡不再重複了,請直接參考上一篇的內容或者本文篇末附件原始碼。
直接使用上一節裡的ServiceConfiguration.cscfg和ServiceDefinition.csdef也行,因為賬戶資訊是一樣的。
第二步:
拖入控制項,製作簡單的登入介面和主聊天介面。這不是重點也不是痛點,請大家直接參看本文篇末附件原始碼。其實聊天室和留言吧的區別不大,使用ASP.NET Ajax的Timer和UpdatePanel讓它每兩秒重新整理一次就行。
第三步:
建立一個Message實體類。
與傳統代碼或由ORM工具產生的實體代碼不同,它需要繼承自TableStorageEntity.
public class Message : Microsoft.Samples.ServiceHosting.StorageClient.TableStorageEntity
{
public Message()
{
PartitionKey = "ChatRoom001";
//取實體時,預設排序是根據RowKey增序列
RowKey = (DateTime.MaxValue.Ticks - DateTime.Now.Ticks).ToString();
}
public string Name { get; set; }
public string Body { get; set; }
//不用定義“訊息發布時間”這種欄位了,
//因為Table Storage有一個自動時間戳記屬性TimeStamp可以自動記錄資料更新時間。
}
第四步:
建立一個MessageDataServiceContext實體類。該類繼承自TableStorageDataServiceContext,也就是間接繼承自DataServiceContext。它的作用是獲得一個對資料服務內容相關的引用。此外,定義一個公用屬性Messages:可返回所有Message類型實體; 增加AddMessage方法:將Message實體存入Table Storage。
public class MessageDataServiceContext : TableStorageDataServiceContext
{
public MessageDataServiceContext(StorageAccountInfo accountInfo)
: base(accountInfo)
{
}
//定義公用屬性Messages,返回所有資料服務上下文中的Message類實體。
public IQueryable<Message> Messages
{
get
{
return this.CreateQuery<Message>("Messages");
}
}
public void AddMessage(string name, string body)
{
//使用DataServiceContext類提供的AddObject方法來存入實體
this.AddObject("Messages", new Message { Name = name, Body = body });
//DataServiceContext類提供的SaveChanges()方法來儲存修改
this.SaveChanges();
}
}
第五步:
取實體:
//初始化賬戶資訊
StorageAccountInfo accountInfo = StorageAccountInfo.GetAccountInfoFromConfiguration("TableStorageEndpoint");
// 自動根據實體類的結構產生Table
TableStorage.CreateTablesFromModel(typeof(MessageDataServiceContext), accountInfo);
// 擷取資料服務內容相關的引用
MessageDataServiceContext context = new MessageDataServiceContext(accountInfo);
// 取前150條Message實體,作為資料來源綁定到messageList中。
IQueryable<Message> data = context.Messages.Take(150);
this.messageList.DataSource = data;
this.messageList.DataBind();
存入實體:
protected void SubmitButton_Click(object sender, EventArgs e)
{
StorageAccountInfo accountInfo = StorageAccountInfo.GetAccountInfoFromConfiguration("TableStorageEndpoint");
MessageDataServiceContext context = new MessageDataServiceContext(accountInfo);
//調用剛才我們定義的AddMessage方法。其實如果你想看上去更爽的話,
//可以把這個方法的入參改為實體
context.AddMessage(this.nameBox.Text, this.messageBox.Text);
}
OK,搞定了!
F5一下看看運行效果吧!
______————————____忐忑不安的分割線______————————______
通過REST方法獲得實體的真實相貌:
可以清楚地看到,這個實體有5個屬性。其中有3個是預設必須有的屬性,只有Body和Name是我們在實體類裡自己定義的。
【附件】
傳說中的StorageClient:StorageClient.rar
本篇原始碼:AzureChatRoom.rar (已與前面章節的原始碼整合)