由於DS的體態豐腴,選用何種序列化就很多的選擇了,我嘗試過如下方法:
1, SOAPFomatter
2, BinaryFomatter
3,SOAPFomatter + SharpZipLib
4,BinaryFomatter + SharpZipLib
5, DataSetSurrogate (http://support.microsoft.com/default.aspx?scid=kb;en-us;829740)
6, DataSetSurrogate + SharpZipLib
7, PAB.CompressDataSet.Wrapper (http://www.eggheadcafe.com/articles/20031219.asp)
若論壓縮效果,第7種辦法是最優秀的,第2名是第6種辦法。
若論速度,第7種和第6種幾乎差不多。。。(最快的好像是第2種)
(區區年前曾做了一個詳細的工程,分別用100/1000/10000條紀錄對上述方法進行測試,然該工程很可能丟到抓娃國了,故詳細數據暫且欠奉,待找回後當補充之)
PAB.CompressDataSet.Wrapper 據上文所說,乃是通過反向工程.NET Compact Framework而得到的壓縮代碼,我估計它也採用了類似於DataSetSurrogate那樣的替代對象來存儲。本來我是很傾向使用這個方法的,可惜這個咚咚沒有源碼(且DLL加了混淆)。。。而反觀第6種,我們則可以輕鬆坐擁全部源碼,所以最後我還是選擇了第6種辦法的。下面的一點代碼,可供各位曬笑:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using System.Data;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.GZip;
/// <summary>
/// 壓縮數據集
/// </summary>
/// <param name="ds"></param>
/// <returns></returns>
public static byte[] CompressDS(DataSet ds)
{
MemoryStream ms = new MemoryStream();
ZipOutputStream zos = new ZipOutputStream(ms);
zos.PutNextEntry(new ZipEntry(ds.DataSetName));
BinaryFormatter bf = new BinaryFormatter();
DataSetSurrogate dss = new DataSetSurrogate(ds);
bf.Serialize(zos, dss);
zos.CloseEntry();
zos.Close();
byte[] ret = ms.ToArray();
ms.Close();
return ret;
}
/// <summary>
/// 解壓數據集
/// </summary>
/// <param name="byt"></param>
/// <returns></returns>
public static DataSet DecompressDS(byte[] byt)
{
MemoryStream ms = new MemoryStream(byt);
BinaryFormatter bf = new BinaryFormatter();
ZipInputStream zis = new ZipInputStream(ms);
zis.GetNextEntry();
DataSetSurrogate dss = (DataSetSurrogate)bf.Deserialize(zis);
zis.Close();
ms.Close();
DataSet ds = dss.ConvertToDataSet();
return ds;
}
基於SharpZipLib實現上面兩個函數後,DS壓縮的任務就完成了。BTW,VS2005裏邊,.NET FW 自帶了CompressStream,我們可以跟SharpZipLib說再見了:)
至於WS怎麼傳輸,在CSDN上看到Tomgus (小橋流水) 老兄轉載的http://www.cnblogs.com/flyskywlh/archive/2005/08/18/217382.html,乃Flyskywlh老兄的大作。
首先我也很同意使用byte[]數組傳輸,非常方便。至於具體WebMethod的方式,我在實際應用中是大量使用實體WebMthod的,比如:
[WebMethod]
public DataSet GetOrders() {}; //獲取所有訂單
[WebMethod]
public DataSet UpdateOrders(DataSet dsOrders){}; //更新指定訂單
因爲採取這種模式,所以系統裏邊有極多的WebMethod(WinformUI僅通過WS交互),一個標準WM的調用流程是:
客戶端壓縮WM中所有DS型的參數-〉調用WM-〉服務器端解壓所有DS型的參數-〉執行實際WM-〉對DS型的返回值進行壓縮-〉客戶端接收並解壓得出結果DS
上述流程的具體實現很麻煩,在客戶端用了AOP的透明代理的概念;服務器端則用了動態調用WS的技術。實現這種“雙代理”的模式後,對於WS端或Winform端,壓縮與不壓縮變得透明瞭,兩方面的程序員都不用再關心這個問題了。而且我覺得“雙代理”還可以爲我們處理其他很多的問題,比如排隊,異步操作,權限等等。那位朋友||大拿||高人有興趣探討這個問題的,小可甚喜!