从IDataReader中读取数据实体.docx
文本预览下载声明
HYPERLINK /vwxyzh/archive/2009/11/12/1601724.html 从IDataReader中读取数据实体
? ? 现在ORM已经是一门非常成熟的技术了,相信用的人不少,加上Linq to sql和Entity Framework的推波助澜,现在还用DataSet和DataTable的人已经越来越少了,不过,如果项目里面不用ORM工具,就不得不回归到DataSet时代吗?
? ? 也许,我们没法改变项目的决策,但是,我们可以自己制造工具。
? ? 这里先忽略掉那些麻烦的sql,调用那个存储过程之类的事情,假设我们已经通过各种手段(不管你是SqlHelper的拥护者还是enterprise library的支持者,或者是自己动手丰衣足食的DIY派),得到了一个IDataReader实例(什么,你不知道IDataReader接口?去 HYPERLINK /zh-cn/library/system.data.idatareader.aspx \t _blank msdn看看吧),并且把msdn上的说明:
? ??提供一种方法来读取一个或多个通过在数据源执行命令所获得的只进结果集流
? ? 简化成:
? ??提供一种方法来读取一个通过在数据源执行命令所获得的只进结果集流
? ? 也就是说,忽略掉一个存储过程返回多个结果集的情况下,我们可以直接把这个IDataReader实例中承载的数据转换为一个ListT的形式。
? ? 读到这里你可能会觉得这样的功能用一个反射就可以搞定了,何必写这么一篇水文?
? ? 不过,这里用的不是常规反射。什么意思?反射还有常规和非常规之分吗?
? ? 常规的反射是直接使用GetProperty和SetValue就可以实现这样的功能了,但是常规反射的问题是反射的效率问题,这样的代码效率是手写代码的1/1000,也就是说,虽然你写的很轻松,但是对CLR来说,这个代码执行的非常累。
? ? 我这里要用的是反射中的Emit技术,动态拼装IL,获得一个高性能转换器,其执行效率至少是手写代码1/2,也就是说,使用这个代码的目的是你写的轻松,CLR执行的也轻松。
? ? 不过,在这个之前,需要先定义数据实体,这个又是每个人的习惯都不一样的东西,我个人是习惯于利用Attribute来表明哪个属性是哪一列,不过考虑到便捷性,会用一个类级的Attribute表明这个类默认为是数据列,或者表明不是默认为是数据列:
?1?????[AttributeUsage(AttributeTargets.Class,?Inherited?=?true,?AllowMultiple?=?false)]?2?????internal?sealed?class?DbResultAttribute?:?Attribute?3?????{?4??5?????????public?DbResultAttribute()?6?????????????:?this(true)?{?}?7??8?????????public?DbResultAttribute(bool?defaultAsDbColumn)?9?????????{10?????????????DefaultAsDbColumn?=?defaultAsDbColumn;11?????????}12?13?????????public?bool?DefaultAsDbColumn?{?get;?private?set;?}14?15?????}16?
HYPERLINK javascript:void(0); 复制代码
? ? 而对于普通的属性,再给与一次修改列名和排除在数据列之外的机会:
?1?????[AttributeUsage(AttributeTargets.Property,?Inherited?=?true,?AllowMultiple?=?false)]?2?????internal?sealed?class?DbColumnAttribute?:?Attribute?3?????{?4??5?????????public?DbColumnAttribute()?{?}?6??7?????????public?string?ColumnName?{?get;?set;?}?8??9?????????public?bool?Ignore?{?get;?set;?}10?11?????}12?
HYPERLINK javascript:void(0); 复制代码
? ? 这样,我们就可以很简单的定义一个数据实体了:
?1?????[DbResult]?2?????pu
显示全部