在前面幾篇《在Web Service中使用dOOdad》中,我提到用ToXml/FromXml來實現在WebService中使用dOOdad。但在具體的項目實踐中,我有遇到一個新問題:將一個業務實體ToXml后得到字符串,然后再對FromXml來解析字符串,獲得新的實體,但這個實體已嚴重失真,其中的DataTable丟失了Schema,會導致部分數據類型(如數據庫中的Image類型)對應的字段不能解析回來,這時調用Save方法時就會出錯。
dOOdad項目源代碼中的ToXml和FromXml:
virtual public string ToXml()
{
DataSet dataSet = new DataSet();
dataSet.Tables.Add(_dataTable);
StringWriter writer = new StringWriter();
dataSet.WriteXml(writer);
dataSet.Tables.Clear();
return writer.ToString();
}
virtual public void FromXml(string xml)
{
DataSet dataSet = new DataSet();
StringReader reader = new StringReader(xml);
dataSet.ReadXml(reader);
this.DataTable = dataSet.Tables[0];
dataSet.Tables.Clear();
}
針對如上所述問題,我的一個解決辦法是重新構造Schema。下面是我的大致思路:
//BusinessEntity中:
virtual public string ToXml()
{
StringWriter writer = new StringWriter();
this.DataTable.WriteXml(writer);//ADO.Net 2.0中DataTable支持WriteXml和ReadXml
return writer.ToString(); //此時的返回值中不含Schema
}
virtual public void FromXml(string xml)
{
this.CreatDataTable();
StringReader reader = new StringReader(xml);
this.DataTable.ReadXml(reader);
this.DataTable = _dataTable;//記得加上這條語句
}
protected virtual void CreatDataTable()
{
//為空,由子類來選擇實現或者不實現。
//當然我們也可以將方法設為abstact,強迫子類來實現,但這樣不太厚道:
//具體的應用中未必會每個業務實體都用到ToXml/FromXml轉換,所以不建議設為abstract
}
//ConcreteClass中:(ps:建議在ConcreteClass中實現自己的代碼,而不要把自己的代碼寫到dOOdad生成的AbstactClass中;因為如果數據庫中表的字段作了局部調整后,AbstractClass中需要作很多瑣碎的改動,倒不如刪掉AbsractClass重新再用MyGeneration來生成代碼,而自己加入的代碼又得重新寫過。)
public override void AddNew()
{
this.CreatDataTable();//重構了一下,抽取出一個方法
base.AddNew();
}
protected override void CreatDataTable()
{
this.DataTable = new DataTable(this.MappingName);
this.AddColumn(Employee.ColumnNames.ID, typeof(int));
this.AddColumn(Employee.ColumnNames.FirstName, typeof(string));
this.AddColumn(Employee.ColumnNames.LastName, typeof(string));
//.........
}
現在就可以通過ToXml和FromXml來實現字符串(不含Schema)與業務實體的近似對等轉換(注意:這里僅僅是說近似對等轉換,因為DataRow的狀態還是丟失了,所以在FromXml后,CurrentRow的狀態處于Added;此時如果是想實現對數據庫記錄的修改,則還需調用AcceptChanges()和SetModified()(MyGeneration學習筆記(6) :在Web Service中使用dOOdad(下) 有講)重新設置其狀態才實現修改。)
補充:上面所講的是實現在網絡中只傳輸DataTable中的數據,而不傳輸DataTable的Schema。事實上,dOOdad中已實現了另一種方法來實現字符串(含Schema和數據)與業務實體的轉換,即Serialize()和Deserialize()方法,且這種序列化是高保真的,可以使得業務實體通過XML字符串實現完全對等轉換。但這種方法的一個不足之處是傳輸數據時需要傳輸Schema,我試過用Serialize()序列化我的項目中的一個業務實體,得到的Xml字符串的長度是3460,而ToXml()得到的字符串的長度是1857,二者相差1603個字符。一個Unicode字符占4個byte,則每次Serialize()得到的結果要比ToXml()得到的結果大1603*4Byte(大約6.26k);而當系統中很多個客戶端同時請求這種獲取數據的WebMethod接口時,就不得不考慮WebService服務器的網絡負擔了。

浙公網安備 33010602011771號