把Sql数据转换为业务数据的几种方法
?
ORM系統必須把數據庫中的數據轉換為業務數據,轉換的方法大致有3種,本文就試圖對它們做一些簡單分析。
1、屬性反射。就是通過反射,獲取業務實體類的各個屬性,然后再設置這些屬性的值。這個方法最簡單、最穩定、通用性最強、可維護性最強、性能最差。例如NHibernate就是用這種方法實現的,它通過IGetter和ISetter接口實現對某個業務實體類屬性的讀取和寫入。DongLiORM的早期版本也是用的這種方法,他通過BusinessObject的屬性索引器實現。其原理就是首先通過獲取某個業務實體類某個屬性的PropertyInfo,然后調用該PropertyInfo的GetValue或者SetValue方法。類似的代碼如下:
PropertyInfo info = BusinessType.GetProperty(PropertyName);
info.SetValue(this, value, null);
比如,現在有一個業務實體類UserItem,其定義如下:
public class UserItem
??? ?{
??????? public UserItem() { }
??????? private string _userid;
??????? private string _username;
??????? private string _pwd;
??????? private string _email;
??????? public string UserID
??????? {
??????????? set { _userid = value; }
??????????? get { return _userid; }
??????? }
?? ?????public string UserName
??????? {
??????????? set { _username = value; }
??????????? get { return _username; }
??????? }
??????? public string Pwd
??????? {
??????????? set { _pwd = value; }
??????????? get { return _pwd; }
??????? }
??????? public string Email
??????? {
??????????? set { _email = value; }
??????????? get { return _email; }
?? }
}
UserItem對應數據庫中的Users表,他的屬性對應Users表的字段UserID,UserName,Pwd,Email。現有一個返回了Users表數據的IDataReader,要把IDataReader轉換為一個UserItem的數組,就用類似如下的方法:
??????? public T[] DbReaderToBusinessObject<T>(IDataReader Reader) where T: new()
??????? {
??????????? List<T> list = new List<T>();???????????
??????????? while (Reader.Read())
??????????? {
??????????????? T Item = new T();???????????????
??????????????? Type BusinessType = Item.GetType();
??????????????? for (int i = 0; i < Reader.FieldCount; i++)
??????????????? {
??????????????????? string PropertyName = Reader.GetName(i);
??????????????????? PropertyInfo info = BusinessType.GetProperty(PropertyName);
??????????????????? info.SetValue(Item,Reader[i],null);
??????????????? }
??????????????? list.Add(Item);
??????????? }
??????????? Reader.Close();
??????????? return list.ToArray();
?}
2、通過XML序列化。就是在讀取數據的時候,從數據庫中返回的Xml形式的數據,然后通過用XmlSerializer的Deserialize方法把數據轉換成業務數據。目前沒有見到有用這種方法實現的產品。其優點同第一種方法,但轉換的效率似乎比第一種方法效率高一些(不過也不會高多少,反序列化實際上也需要反射),但是增加了從數據庫中返回數據的數據量,而且對于已經編譯了的業務實體類也無能為力。其實現方法類似下面的過程(以Sql Server 2000為例)。
?? 業務實體類的定義:
?? [Serializable]
?? [XmlRoot("Users")]
??? public class UserItem
??? {
??????? public UserItem(){}
??????? private string _userid;
??????? private string _username;
??????? private string _pwd;
??????? private string _email;
??????? [XmlAttribute("UserID")]
??????? public string UserID
??????? {
??????????? set { _userid = value; }
??????????? get { return _userid; }
??????? }
??????? [XmlAttribute("UserName")]
??????? public string UserName
??????? {
??????????? set { _username = value; }
??????????? get { return _username; }
??????? }
??????? [XmlAttribute("Pwd")]
??????? public string Pwd
??????? {
????????? ??set { _pwd = value; }
??????????? get { return _pwd; }
??????? }?????
??????? [XmlAttribute("Email")]
??????? public string Email
??????? {
??????????? set { _email = value; }
??????????? get { return _email; }
??????? }
?? }
?
??轉換過程:
?? List<UserItem> UserList = new List<UserItem>();
?? string XmlSql = "select * from Users for xml auto";
??? SqlCommand cmd = new SqlCommand(XmlSql, con);
?cmd.CommandText = XmlSql;
??? XmlReader r = cmd.ExecuteXmlReader();
??? XmlSerializer sr = new XmlSerializer(typeof(UserItem));
??? while (r.Read())
??? {
??????? UserList.Add(sr.Deserialize(r) as UserItem);
??? }
r.Close();
?
3、在業務實體類中自定義一個把Sql數據解析成業務數據的方法。這種方法的優點是轉換的效率非常高,在理想的情況下,和Ado.net的速度不相上下,缺點是必須對每個業務實體類實現一個把Sql數據解析成業務數據的方法。手工編碼的工作量非常大,配上專門的代碼輔助工具,可以減輕工作量,但是,如果數據結構需要改動,則改動的地方比較多,容易出錯。用這種方法實現的有NBear V3,DongLiORM 1.2等。比如NBear V3中就有幾個專門方法,比如:
public override void SetPropertyValues(System.Data.IDataReader reader);
public override void SetPropertyValues(System.Data.DataRow row);
?
而DongLiORM則是通過重寫索引器(還是上文的UserItem):
public override object this[string PropertyName]
???? {
??????????? get
??????????? {
??????????????? switch (PropertyName)
??????????????? {
??????????????????? case "UserID": return _userid;
??????????????????? case "UserName": return _username;
??????????????????? case "Pwd": return _pwd;
??????????????????? case "Email": return _email;
??????????????? }
????????? ??????return base[PropertyName];
??????????? }
??????????? set
??????????? {
??????????????? switch (PropertyName)
??????????????? {
??????????????????? case "UserID": _userid = (string)value; return;
??????????????????? case "UserName": _username = (string)value; return;
??????????????????? case "Pwd": _pwd = (string)value; return;
??????????????????? case "Email": _email = (string)value; return;
??????????????? }
??????????????? base[PropertyName] = value;
??????????? }
}
?
“魚我所欲也,熊掌亦我所欲也,二者不可得兼,舍魚而取熊掌者也”。系統的性能和代碼簡單性,二者不可兼得,到底我們更需要誰呢?
?
狂想:假設我們有一個這樣的東西,他能夠在運行時候改變現有的某個類(比如UserItem)的某個屬性(比如索引器)/方法(比如SetPropertyValues)就好了,這樣我們就可以在設計的時候寫非常少的代碼,而又能夠獲得比較高的運行效率。可惜PropertyBuilder等只能對動態類有用,幫不上忙。
?
我所想到方法的就這些,各有優點和缺點,不知各位有沒有其他的方法,能讓統的性能和代碼簡單性和諧統一。
?
原貼地址:http://www.cnblogs.com/Yahong111/archive/2007/07/27/833028.html
轉載于:https://www.cnblogs.com/zhuawang/archive/2011/08/17/2142825.html
總結
以上是生活随笔為你收集整理的把Sql数据转换为业务数据的几种方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Thread的join方法使用解析
- 下一篇: 在Activity的Title中加入进度