.Net 1.X平台的Web Service (WS) 資料流壓縮方案

.Net 1.X平台的Web Service (WS) 資料流壓縮方案

  由於目前有些平台仍是在.Net 1.X上面,雖然GZipStream可以壓縮資料流,但它必需在.Net 2.0以上的平台才能用,但也不代表.Net 1.X就只能乖乖的認命,接受這個結果,其實在.Net 1.X上,也有一個方法可以做到資料流的壓縮,微軟有提供一個物件DataSetSurrogate來協助開發人員不用花太多的時間在Coding上,就可以達成目標.

  

  仔細去看DataSetSurrogate的原始碼後,大至上就可以了解到它是怎麼去"簡化"資料量,怎麼運用多個Array List及HashTable去儲存DataSet裡的資料,雖然壓縮率沒有GZipStream來的高,但也算很優了,而運用也相當的簡單,不用寫太多的程式碼在上面,以下就是程式碼部份的簡介 :

 

  首先,要去下載DataSetSurrogate的這個檔案,下載解壓後,可以看到VB及CSharp的目錄,這兩個目錄都一樣,只是一個是用VB寫的,另一個是C#,而這目錄以下,有三個目錄 : DataSetSurrogate,DSServer,TestSurrogate.而TestSurrogate為測試的專案,DSServer是測試專案的DataAcess的部份,除了要測試,不然可以不用管它,因為我們要用的是DataSetSurrogate,剛解壓是沒有編譯過的,所以要先Complier這個專案,才能得到我們要用的DLL物件.

 

當我們得到DataSetSurrogate這個物件後,就可以拿到我們的專案裡用,當然,不論是Client還是Server,都要記得先將DataSetSurrogate加入參考才能用,以下就是程式範例 :

Server Side :

using System.Runtime.Serialization.Formatters.Binary;
using System.IO;



        [WebMethod]
        public byte[] GetDSBinary()
        {
            try
            {
                DataSetSurrogate dss=new DataSetSurrogate(LoadData().Copy());
                BinaryFormatter bf = new BinaryFormatter();
                MemoryStream ms=new MemoryStream();
                bf.Serialize(ms,dss);
                return ms.GetBuffer();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }



        private DataSet LoadData()

        {

            try
            {
                DataSet ds=new DataSet();

                //從資料庫取得資料

                return ds;

            }

            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

 

 

Server端的Web Service就只有這樣,就可以了,所以程式碼部份,真的很少. 而Client端的部份,也是一樣,並不多.

Client Side :

using System.Runtime.Serialization.Formatters.Binary;
//using 剛剛做好的WebService

 

        private void button1_Click(object sender, System.EventArgs e)
        {
            WS.Service1 w=new WSGet.WS.Service1();//new 剛剛的WebService
            try
            {
                dataGrid1.DataSource=null;
                this.Cursor=Cursors.WaitCursor;
                byte[] bt=w.GetDSBinary();

                MemoryStream ms=new MemoryStream(bt);

                BinaryFormatter bf=new BinaryFormatter();    
                object obj=bf.Deserialize(ms);
                DataSetSurrogate dss=(DataSetSurrogate)obj;
                dataGrid1.DataSource=dss.ConvertToDataSet().Tables[0];
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                this.Cursor=Cursors.Default;
            }            
        }
 

 

Client端這樣也就OK了,測試了一下壓縮量的差異,結果如下表 :

 壓縮前壓縮後壓縮比
GZipStream18,368,067 bytes4,445,278  bytes75%
DataSetSurrogate6,563,150 bytes2,872,540 bytes45%

雖然有20%的差異,但也是不錯了,不知道GZipStream+Serialize+DataSetSurrogate會是什麼樣的結果~(預計效果可能不大,依據微軟的說法,.Net 2.0的BinaryFormatter已將DataSet的內容以精簡化之二進位制格式化,所以不需再用DataSetSurrogate)

 

  之所以會去翻出.Net 1.X的舊平台解決方案,主要也是因為現在公司的Client端部份仍是.Net1.X,無法在2.0上運作,雖然Server端是2.0的,也是無法使用GZipStream,但說到這裡,有一個重點出現了,我嘗試過用DataSetSurrogate放在.Net2.0的執行,從2.0的Server端丟回到1.X的Client端,結果會跳出錯誤訊息"可能原因為版本不相符。型別 System.Globalization.CompareInfo 有 2 個成員,但還原序列化後的成員數目卻為 3。".把Server設為1.X就OK了,初步判斷,應該是BinaryFormatter的問題,因為.Net1.X與2.0的不同,如上所述"Net 2.0的BinaryFormatter已將DataSet的內容以精簡化之二進位制格式化",而1.X的並沒有,所以可能因此,在這部份上,造成我在Deserialize時,會發生錯誤,這個問題目前還沒解決,就看看大家有沒有答案囉.

 

參考資料 :

ADO.NET 1.x Dataset 序列化問題探討

增進資料集序列化和遠端效能

下載 : DataSetSurrogate