Table Storage是一個模擬關聯式資料庫的結構化資料(structured data)存取服務,它就像是在雲端中的表格一樣,允許應用程式可以在Table儲存體中宣告並存取自己的資料結構。
Table Storage是一個模擬關聯式資料庫的結構化資料(structured data)存取服務,它就像是在雲端中的表格一樣,允許應用程式可以在Table儲存體中宣告並存取自己的資料結構。而在Table儲存體的內部,則是橫跨多個伺服器與磁碟儲存區的基礎架構,微軟的Windows Azure開發小組將核心內的所有作業都隱藏起來,只顯露出一個REST API供外部應用程式存取,而且都是透過相同的URL來呼叫,因此Table基本上並不是儲存在應用程式所在的VM,而是在Windows Azure Platform內部自動規範的儲存區域中。但是它雖然可以保存結構化資料,然而實際上它是以XML的方式儲存,架構上是以NoSQL的概念為主,所以不要將它和一般的DBMS的表格聯想在一起,它沒有辦法與DBMS一樣執行彙總與表格聯結(JOIN),當然也不相容於SQL指令。
與BLOB相似,Table Storage也有容器的概念,不過在Table Storage中的容器稱為表格,每一筆資料都是以表格為容器保存的,稱為Entity,每一筆Entity因為都是XML(如下列示之XML資料),所以必須要符合XML的規範,否則會在系統自行序列化時發生錯誤,簡單的說,只要使用最基本的.NET資料型別,多半都可以順利執行。每一筆Entity除了自己本身的資料外,固定要保存PartitionKey, RowKey與Timestamp三筆資料:
Table Storage與BLOB Storage一樣,會提供REST API,不過特別的是Table的REST API是以OData(Open Data Protocol)為標準開放的,它是源自於WCF Data Service(前身為ADO.NET Data Service),所以.NET開發人員只要利用.NET Framework內建的Data Service Client(System.Data.Service.Client)就能順利存取它,更可以直接使用LINQ。
在Table Storage的程式設計上,開發人員會使用到CloudTableClient物件,這是Table Storage用戶端的入口,另外會使用到TableServiceEntity以及TableServiceContext兩個類別,TableServiceEntity是用來宣告Entity的內容的,因為Table Storage不可能知道Entity內的資料有哪些,應用程式必須告訴它,所以程式中一定要有一個資料類別是繼承自TableServiceEntity,內含必要的資料型別,如下列程式碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Services;
using System.Data.Services.Client;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
namespace ContactManagerWeb
{
public class Contact : TableServiceEntity
{
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Cellphone { get; set; }
public Contact()
{
base.PartitionKey = "Contact";
base.RowKey = Guid.NewGuid().ToString();
}
public Contact(string Name, string Address, string Phone, string Cellphone)
{
base.PartitionKey = "Contact";
base.RowKey = Guid.NewGuid().ToString();
this.Name = Name;
this.Address = Address;
this.Phone = Phone;
this.Cellphone = Cellphone;
}
}
}
而TableServiceContext則可以當做遠端的資料來源,所有針對Table Storage的OData查詢都是由這個類別發動,它所屬的CreateQuery<T>()方法可以建立對Table Storage的查詢,再利用LINQ指令,即可輕鬆的對Table Storage進行資料的查詢與回傳的工作。
DataServiceQuery<Contact> queryProvider = context.CreateQuery<Contact>("Contacts");
this.gvContactViewer.DataSource = from contacts in queryProvider
select contacts;
對Table Storage的資料增修刪當然也不是問題,只要透過物件的 Add/Update/Delete 操作,最後呼叫TableServiceContext.SaveChanges()即可。
protected void cmdOK_Click(object sender, EventArgs e)
{
CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("DataSource");
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
TableServiceContext context = tableClient.GetDataServiceContext();
if (EditState.Add == ((EditState)ViewState["EditState"]))
{
context.AddObject("Contacts",
new Contact(this.txtName.Text, this.txtAddress.Text, this.txtPhone.Text, this.txtCellphone.Text));
}
else
{
var queryItem = from contacts in context.CreateQuery<Contact>("Contacts")
where contacts.RowKey == ViewState["EditContactID"].ToString()
select contacts;
Contact contact = queryItem.First<Contact>();
contact.Address = this.txtAddress.Text;
contact.Name = this.txtName.Text;
contact.Phone = this.txtPhone.Text;
contact.Cellphone = this.txtCellphone.Text;
context.UpdateObject(contact);
}
context.SaveChangesWithRetries(SaveChangesOptions.Batch);
this.gvContactViewer.DataSource = from contacts in context.CreateQuery<Contact>("Contacts")
select contacts;
this.gvContactViewer.DataBind();
this.mvContactManager.SetActiveView(this.vContactViewer);
ViewState["EditState"] = EditState.None;
ViewState["EditContactID"] = null;
context = null;
storageAccount = null;
tableClient = null;
}
最後要提的是,Table Storage在使用上有些限制: