天天看點

多樣化實作Windows Phone 7本地資料通路<4>——Rapid Repository

<a href="http://blog.51cto.com/attachment/201201/223006299.jpg" target="_blank"></a>

在進入開發前 我們先來OverView一下這個Repid repository.

<a href="http://blog.51cto.com/attachment/201201/223104307.jpg" target="_blank"></a>

10月份釋出的Windows Phone 7 支援通路資料幾種方式為: XML、Isolated Storage[獨立存儲]、Cloud[雲存儲],微軟官方并沒有給廣大WP7開發者提供相關的本地資料庫通路的API. 這曾經讓很多習慣嵌入式開發的DVp 很是頭疼.

Rapid Repository是一個基于Apache 2.0協定開源的項目,本月11月7日剛剛釋出了第一個1.0正式版本[10月31日釋出第一個Beta版本],Rapid Repository在存儲資料本質還是是基于Windows Phone 7 獨立存儲的一個NoSQL資料庫[即文檔資料庫]. 這裡我稍微說一下關于NoSQL和傳統Relation DataBase[關系型資料庫]特點和差別.

NoSql資料庫和Relation DataBase相比的優勢是不需要建立Schema,表或者是存儲過程等關系資料庫的對象。隻需要根據你的需要定義你的實體然後把它儲存到資料庫就可以了[其實就是說白了就像DB4O具備的面向對象資料庫.],同時支援LINQ to Object方式查詢資料庫.

<a href="http://blog.51cto.com/attachment/201201/223120519.jpg" target="_blank"></a>

對于這個目前尚是第一個版本Repid Repositroy, 我可以在第一個版本總能省去更多細枝末節看到Repid Repository内部基于WP7獨立存儲實作資料處理機制如何建構的.

對于Repid Repostitory 的CUD[添加/更新/删除]資料操作 實際上CRU操作的是存儲在WP7 獨立存儲空間中已經把實體序列化的JSon格式的檔案.

在存儲空間中存儲一個實體類,則需要通過Add()和Update()方法同時把Entity序列化成Json格式. 這意味着你可以在WP7中村複制的對象和屬性. List&lt;&gt;基本資訊等.

當你通過GetById()和GetAll()方法實作Linq 同Object查詢時 Repid 則通過發序列化方式把存儲在WP7空間的Json檔案轉化成Entity Class.而RapidContext.Current.SaveChanges() 方法則保持所有目前關于Repid資料庫操作改變

.看來Repid 采用對象可序列化 把序列化JSon格式檔案存在獨立存儲空間進行操作. 所有操作都是在記憶體中進行的.

<a href="http://blog.51cto.com/attachment/201201/223149404.jpg" target="_blank"></a>

建立一個Windows Phone 7 Application 命名RepidDBLocalDemo: 添加RepidRepository.DLL引用:

<a href="http://blog.51cto.com/attachment/201201/223200482.jpg" target="_blank"></a>

建立測試頁面MainPage.Xaml:

<a href="http://blog.51cto.com/attachment/201201/223210649.jpg" target="_blank"></a>

MainPage頁面儲存一個實體類EntityClass 貨物Product資訊到Repid資料庫中,定義好頁面後,如下需要定義 Product實體:

using RapidRepository;     

namespace RepidDBLocalDemo.EntityModel     

{     

    /// &lt;summary&gt;     

    /// Define the Product Model to Store     

    /// Author:chenkai Date:2010年11月16日18:10:47     

    /// &lt;/summary&gt;     

    public class Product :IRapidEntity    

    {    

        public Guid Id { get; set; }    

        public string ProductName { get; set; }    

        public string ProductCatory { get; set; }    

        public ProductPackage ProductSpec { get; set; }    

        public DateTime CreateDate { get; set; }    

    }    

   public class ProductPackage    

        public string PId { get; set; }    

        public string PackageSpec { get; set; }    

實體類Product定義中發現繼承了一個接口IRapidEntity, 這個IRapidEntity我們檢視一下它的定義:

namespace RapidRepository     

    public interface IRapidEntity     

    {     

        Guid Id { get; set; }     

    }     

you see! 其實繼承IRapidEntity接口目的就是為了給實體類強制加了一個Guid屬性.這也不難了解, Guid[全球唯一辨別符]值就是這個唯一的辨別碼來辨別實體類. 這主要是為了當我們Repid資料庫中存儲多個實體通過Guid來唯一辨別實體類. 在Product用屬性Id來實作使用者自定義Guid.

Product實體類把ProductPackage規格類作為ProductSpec屬性. 這就是初步複雜類型實體

定義完實體類Product後,對于實體類存儲操作我們需要定義一個對應的ProductRepository操作類:

using RapidRepository.Context;     

using RepidDBLocalDemo.EntityModel;     

    /// Define the ProductRepository     

    /// Author:chenkai Date:2010年11月16日18:45:19    

    /// &lt;/summary&gt;    

    public class ProductRepository :RapidRepository&lt;Product&gt;    

        /// &lt;summary&gt;    

        /// Override Base Add new Product EntityModel Method    

        /// Author:chenkai Date:2010年11月17日10:21:51    

        /// &lt;/summary&gt;    

        public override Product Add(Product entity)    

        {    

            var newproduct = base.Add(entity);    

            RapidContext.CurrentContext.SaveChanges();    

            return newproduct;    

        }    

        /// use GUID Delete EntityModel Class    

        /// &lt;param name="id"&gt;Entity Guid&lt;/param&gt;    

        public override void Delete(Guid id)    

            base.Delete(id);    

   ]  

        /// Update the EntityModel     

        public override Product Update(Product entity)    

            var updateproduct = base.Update(entity);    

            return updateproduct;    

ProductRepository類是對實體Product進行資料庫操作時使用類.ProductRepository 繼承了RapidRepository類,其實RepidRespository是定義目前Repid資料所有CRUD操作:

public class RapidRepository&lt;TEntity&gt; where TEntity : global::RapidRepository.IRapidEntity     

   {     

       public RapidRepository();     

       public virtual TEntity Add(TEntity entity);     

       public virtual void Delete(Guid id);     

       public virtual void Delete(TEntity entity);     

       public virtual IList&lt;TEntity&gt; GetAll();     

       public virtual TEntity GetById(Guid id);    

       public virtual TEntity Update(TEntity entity);    

   } 

對于Repid資料庫所有對源資料發生變動需要使用repidContent.CurrentContent.SaveChange()方法強制儲存.才能生效.

MainPage添加對Repid資料庫相關引用:

//Add References     

using RapidRepository.Database;     

using RepidDBLocalDemo.EntityModel; 

點選Save按鈕觸發儲存一個Product實體到Repid資料庫中并确認是否儲存成功:

private void Saveinfor_Click(object sender, RoutedEventArgs e)     

      {     

         //Save Product  Entity     

         try     

         {     

             if (!string.IsNullOrEmpty(this.Product_Id.Text) &amp;&amp; !string.IsNullOrEmpty(this.Product_Name.Text)     

                 &amp;&amp; !string.IsNullOrEmpty(this.Product_catory.Text))     

             {     

                 Product newproduct = new Product     

                 {    

                      Id=new Guid(),    

                      ProductName=this.Product_Name.Text,    

                      ProductCatory=this.Product_catory.Text,    

                      ProductSpec=new ProductPackage    

                      { PId=this.Product_Id.Text, PackageSpec="ProductSpec_Value"},    

                      CreateDate=DateTime.Now    

                 };    

                 //Save The Product Entity    

                 ProductRepository productrep = new ProductRepository();    

                 Product saveproduct=productrep.Add(newproduct);    

                 //query the Entity Confirm Entity is Save?    

                 Product queryproduct = productrep.GetById(saveproduct.Id);    

                 if (queryproduct != null)    

                     MessageBox.Show("Save Sucess!\r\n産品編号:"    

                         +queryproduct.ProductSpec.PId+"\r\n産品名稱:"    

                         +queryproduct.ProductName+"\r\n産品分類:"    

                         +queryproduct.ProductCatory+"\r\n建立時間:"    

                         +queryproduct.CreateDate.ToString());    

                 else    

                     MessageBox.Show("Save Fail!");    

             }    

         }    

         catch (Exception se)    

         {    

             MessageBox.Show("sorry you get Exception:" + se.Message);    

     } 

輸入資料後儲存效果:

<a href="http://blog.51cto.com/attachment/201201/223219468.jpg" target="_blank"></a>

上面儲存驗證是先把産品資訊儲存Repid資料庫中,然後通過查詢方式擷取到已經儲存的Product資訊,以确認資訊正确儲存,查詢方式目前在Repid1.0中隻有兩種方式GetById()和GetAll():

/// &lt;summary&gt;     

/// query a Entity by Guid     

/// &lt;/summary&gt;     

public override Product GetById(Guid id)     

    return base.GetById(id);     

}     

/// &lt;summary&gt;    

/// Get All Entity Model    

/// &lt;/summary&gt;    

/// &lt;returns&gt;List of Sotre Model&lt;/returns&gt;    

public override IList&lt;Product&gt; GetAll()    

{    

    return base.GetAll();    

很明顯GetById通過Guid方式唯一查詢一個Entity實體.這裡你明白了為何要在Product中繼承接口的目的. GetAll方式則擷取repid資料庫目前所有實體資料.傳回的是一個實作接口IList&lt;Entity&gt;集合.

其他簡單的CRUD操作基本雷同, 不在贅述.注意有一點就是當對Repid資料庫發生一定操作改變資料源是一定不要忘了采用PepidContent.CurrentContent.SaveChanges();方法儲存修改.

<a href="http://blog.51cto.com/attachment/201201/223229130.jpg" target="_blank"></a>

相信用過Nhibernate對資料ORM[Obeject-Relation-Mapping]映射來替代關系型資料庫這種解決方案. 我從開始用Repid一直對它資料性能保持質疑态度. 雖然作者說能夠實作WP7中資料處理基本要求. 但還是對它性能上沒有相關測試案例和官方的關于這個問題比較有說服力資料公布.

另外昨天在Group中有人質疑問到Repid資料既然通過實體序列化成Json檔案格式然後存儲到獨立存儲空間中. 那麼這個把實體序列化Json格式這個工作在哪裡做呢? 我們理清一下Repid存儲資料過程:

<a href="http://blog.51cto.com/attachment/201201/223239129.jpg" target="_blank"></a>

Repid總結歸納一下存儲資料過程: Define Entity[定義實體]——Add Entity[添加實體]——Entity Serializable Json File[把實體序列化成JSon檔案]——Store JSon File Isolate Space[把序列化JSon檔案存儲在WP7獨立存儲空間中].

其中把Entity實體序列化成一個Json檔案這個操作被Repid資料庫給封裝在底層.開源資料庫的作者并沒有把相關方法暴露給使用者來操作. 所有有人說看不到Entity實體轉化成JSon檔案這個過程 其實是被作者封裝在底層隐藏起來.這樣一來使用者隻需要關心他們與實體操作相關方法二無需關注具體這個實體時如何序列化的并存儲起來過程. 更加簡化使用者關注地方 簡便 實用.

關于資料性能質疑 目前上沒有任何資料能夠初步驗證Repid,由于本篇幅有限.我會在下一篇用實際處理資料方式示範Repid資料庫在Windows Phone 7上性能體驗.下一篇幅 會相關介紹repid緩存機制和延遲加載相關功能.如上市Repid資料在Windows phone 7資料通路.如有任何建議和意見請在留言中提出..

<a href="http://down.51cto.com/data/2359672" target="_blank">附件:http://down.51cto.com/data/2359672</a>

本文轉自chenkaiunion 51CTO部落格,原文連結:http://blog.51cto.com/chenkai/764139