iT邦幫忙

DAY 15
6

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三筆資料:

  1. PartitionKey:識別分割區的資料,由Table Storage伺服器依需要進行Entity的群組化,以加快存取時間。
  2. RowKey:每個Entity的唯一識別碼,在同一個Table內要是唯一的。
  3. Timestamp:每個Entity的最後存取時間。

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在使用上有些限制:

  1. 欄位名稱要依照C#的identifier(識別子)的規範來命名,最長255字,若XML規範未支援的C#規範也不可以使用。
  2. 欄位數最多252個(不含系統必要的3個),且整個資料列的資料長度不可以超過1MB。
  3. 系統欄位Timestamp不可以修改(若在POST和UPDATE時入Timestamp的話,系統會略過)。
  4. 不可以使用『\』、『/』、『#』以及『?』四種字元。
  5. 每次的新增、修改與刪除作業,都必須要指定Partition Key以及Row Key。
  6. Partition Key和Row Key長度最大1KB,同時在相同的Partition Key中,Row Key對於每個資料列都必須是唯一的值。
  7. 所有欄位的資料型別都必須要符合EDM(Entity Data Model)的資料型別規範。

Reference:
http://msdn.microsoft.com/en-us/windowsazure/wazplatformtrainingcourse\_exploringwindowsazurestoragevs2010\_topic2#\_Toc303848586


上一篇
Storage Service (1): BLOB Storage
下一篇
Storage Service (3): Queue Storage
系列文
雲端運算與 Windows Azure Platform 開發32

1 則留言

0
chiounan
iT邦研究生 1 級 ‧ 2011-10-21 11:08:17

讚很認真

我要留言

立即登入留言