asp.net c# 轻量ORM框架开发之反射与动态编译

对象关系映射,靠纯手打,是个超级繁琐又类的苦力活,即便它能给你再高的运行效率,但是也会损失开发效率。

c#在netframework中其实已经提供了ORM框架了,叫做entity framework,这个框架其实已经做的蛮好的了,但是框架实在是太重,重到写出来的代码在配置不那么好的电脑上跑起来都卡顿。

因此我们决定自己写这么一个框架,一来重在轻量;二来,就是想探探路,看看ORM框架到底是怎么做出来的。

当然,让我自己凭空造楼是做不到的,但是我们可以借鉴,尤其是在互联网这么发达的时代,去github看看别的的开源代码就OK了。

一、反射。

首先我们要解决的就是当从数据库中取出值来了之后,怎么直接赋值给相应的对象的属性的问题,我们记得,传统的做法就是

dt.Rows[i][“ID”]

这么一个一个字段去写,碰到字段比较多的表,那就会打半天了。

反射,就是要获得该类的变量的名称,然后赋值给该变量:

 代码如下 复制代码

public List<T> ExecSelect<T>(string sqlCmd) where T : new()
        {
            List<T> list = new List<T>();
            DataTable dt = Select(sqlCmd);

            if (dt.Rows.Count == 0)
            {
                return list;
            }

            PropertyInfo[] properties = ReflectionHelper.GetProperties(new T().GetType());

            for (int i=0;i<dt.Rows.Count;i++)
            {
                T entity = new T();
                foreach (PropertyInfo property in properties)
                {
                    String name = property.Name;
                    ReflectionHelper.SetPropertyValue(entity, property, dt.Rows[i][name]);
                }
                list.Add(entity);
            }

            return list;

        }

以上的T就是一种泛型,至于泛型是什么,自行百度。

GetProperties函数即是泛型用于获取类的变量的方法,它有一些参数,包括获取变量为public修饰等等参数:

 代码如下 复制代码
 public static PropertyInfo[] GetProperties(Type type)
        {
            return type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        }

二、Value.

既然我们已经通过GetProperties获取了该类的属性,那么通过SetValue直接给其赋值就好了,问题是,如果我们从数据库中取出来的值和它不匹配呢,因此我们需要转化Value类型。

 代码如下 复制代码

if (Convert.IsDBNull(value) || (value == null))
            {
                return null;
            }

            string typeName = type.FullName.ToString();
            System.Console.WriteLine(typeName);

            if (type == typeof(System.Nullable<UInt16>))
            {
                value = Convert.ToUInt16(value);
            }
            else if (type == typeof(System.Nullable<UInt32>))
            {
                value = Convert.ToUInt32(value);
            }
            else if (type == typeof(System.Nullable<UInt64>))
            {
                value = Convert.ToUInt64(value);
            }
            else if (type == typeof(System.Nullable<Int32>))
            {
                value = Convert.ToInt32(value);
            }
            else if (type == typeof(System.Nullable<Int64>))
            {
                value = Convert.ToInt64(value);
            }

            switch (typeName)
            {
                case "System.String":
                    if (!isNullOrEmpty(value))
                        value = value.ToString();
                    break;
                case "System.Boolean":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToBoolean(value);
                    break;
                case "System.Int16":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToInt16(value);
                    break;
                case "System.Int32":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToInt32(value);
                    break;
                case "System.Int64":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToInt64(value);
                    break;
                case "System.Double":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDouble(value);
                    break;
                case "System.Float":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDouble(value);
                    break;
                case "System.Single":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDouble(value);
                    break;
                case "System.Decimal":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDecimal(value);
                    break;
                case "System.DateTime":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDateTime(value);
                    break;
            }

            return value;
        }

三、反射与动态编译。

Reflection真的是个好东西,但是net4.0后会有一个更好的东西:dynamic,要知道反射其实是很费效率的,但是动态编译就会快的多,如果你不理解dynamic,那么以下的例子就会告诉你这两者的区别:

public void test()
        {
            SomeClass c = new SomeClass();

            PropertyInfo property = c.GetType().GetProperties()[0];

            StartTest("begin reflection.");

            for (int i = 0; i < 1000000; i++)
            {
                property.SetValue(c, i, null);
            }

            EndTest("end reflection");

            IDynamicPropertyInfo dproperty = new DynamicType(c.GetType()).GetProperties()[0];

            StartTest("begin dynamic.");

            for (int i = 0; i < 1000000; i++)
            {
                dproperty.SetValue(c, i, null);
            }

            EndTest("end dynamic");
        }

那么这两者的时间差呢:

—— Test started: Assembly: Pixysoft.Framework.Reflection.dll ——

begin reflection.
end reflection
00:00:09.0625000

begin dynamic.
end dynamic
00:00:00.0468750

差别就太远了,所以如果你觉得因为反射你的程序变慢了,不如试试动态编译。

时间: 2024-08-03 12:35:25

asp.net c# 轻量ORM框架开发之反射与动态编译的相关文章

C#发现之旅第十二讲 基于反射和动态编译的快速ORM框架(下)

对于字符串类型的属性,其默认值就是"DBNull".而对于其他的整数或者日 期类型的属性,并没有默认值,因此是无条件的插入到数据库中. 我们使用以下的代 码来生成上述代码文本 myWriter.WriteLine("public override int FillInsertCommand( System.Data.IDbCommand cmd , object objRecord )"); myWriter.BeginGroup("{"); m

使用CakePHP框架开发网站

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 现如今成熟的PHP开发框架有很多种,YII,zendframwork,国内轻量型框架Thinkphp,还有开发效率很高的CakePHP.公司可以根据自己的需求选择合适的开发框架,在这里,小编以自己公司使用的开发框架CakePHP作为重点介绍,阐述它的优点. CakePHP的简要介绍: PHP框架已被确认为最流行的编码框架,以创建网站.已经出现

云连锁反应:中间件栈添层 应用更轻量

中间件栈增加了层以及对轻量应用的开发需求将导致更好的云访问. 过去10年,软件的开发和部署方式已经出现了巨大的转变.2005年初时,企业服务总线还很流行,而云尚处在青春期,还在等待这Amazon EC2/S3的降临.现在,开发者可以利用的技术数量出现了爆发式增长,云的无所不在增加了中间件栈的层次,据专家说. 总部位于英国乌斯特郡的咨询公司C2B2的首席顾问Matt Brasier说,所有现有技术经过10年的发展已经极大地成熟了,为中间件栈开发者和应用架构师提供了更多的多样性.这一架构性选择延伸到

DataRabbit 轻量的ORM框架(17)-- 使用DataRabbit的最佳实践

     在DataRabbit 轻量的数据访问框架(12)-- 将DataRabbit融入架构 一文中介绍了如何将DataRabbit与三层架构结合起来,但是,在实际的项目中,每一层是如何使用DataRabbit的了?本文将展示作者在项目中使用DataRabbit的标准做法.      我们以CompanyUser表和MemberShip表为例说明如下:      比如我们有个虚构的业务流程(仅用于示例)如下:根据UserID找到对应的MemberShip记录,然后根据MemberShip记录

DataRabbit 轻量的数据访问框架(13)--DataRabbit 3.0 ORM性能大幅度提升!

   DataRabbit 3.0重写了DataRabbit 2.0的ORM实现的内核,性能提升了90倍左右,结果是DataRabbit 3.0的ORM性能与直接使用ADO.NET的性能已经非常接近.这是如何做到的?   主要是基于两点:(1)DataRabbit 2.0 基于泛型和反射实现,而DataRabbit 3.0 基于泛型和Emit动态程序集实现.   DataRabbit 2.0使用反射机制将值在O和R之间传递,如此大量使用反射会使性能折损不少.DataRabbit 3.0在运行时,

DataRabbit 轻量的ORM框架(18)-- 捕获数据库访问异常的详细信息

     最新版本的DataRabbit(版本号:V3.2)新增一项重要功能--可以捕获访问数据库时产生的异常的详细信息,包括:异常对象.Sql语句.sql参数的名称和值.这是由IDBOperationLogger接口提供支持的.     /// <summary>     /// IDBOperationLogger 用于捕获住DB操作异常.可以用于记录DB操作失败时的语句和参数.     /// </summary>    public interface IDBOperati

.NET框架下ORM的一个轻量高效替代方案

从最初做JAVA开发到现在致力于.NET平台,经手的大大小小的项目也不在少数.刚开始每写成一个程序还能获得不少的成就感,但随着开发年限的增加.项目代码行的增加,写代码更多时候变成一种糊口的工具而非兴趣时,越来越被大量相似的SQL搅得头晕脑胀,尤其维护旧程序时,对SQL的调试更是让人头大.于是,一直致力于找出一个方法,可以不用每次都去编写那些烦人的SQL. 答案是肯定的,JAVA平台下有个Hibernate的ORM框架,它应该是最早的一个成熟的ORM软件,貌似可以解决我的问题.迫不及待的下载.使用

CYQ.Data 轻量数据层之路 bug反馈、优化建议、最新框架下载

重要说明: 所有相关的版本及下载,均转移并发布于秋色园QBlog的CYQ.Data专题博客中:http://www.cyqdata.com/cyqdata   欢迎大伙在使用过程若遇bug可及时反馈,如果有好的建议,请留言!!!   相关开源进群讨论:详见:CYQ.Data 轻量数据层之路 框架开源 所有信息汇总一览:详见:CYQ.Data 轻量数据层之路 框架开源系列 索引    V1.3版本[华丽的开始] 框架下载:V1.3 版本 点击下载 源码下载:V1.3 源码 点击下载   V1.4版

DataRabbit 轻量的数据访问框架(06) -- IRelationAccesser

   (完全限定类名:DataRabbit.Relation.IRelationAccesser)       前面介绍的IOrmAccesser是对单表进行ORM访问,而ITableAccesser是对单表进行基于关系的访问,如果我们要进行联合查询这样的跨表搜索,则使用它们就无法达成目标.这时,你可以使用IRelationAccesser.与IOrmAccesser和ITableAccesser的针对性不同(它们针对数据库中的某个表),IRelationAccesser针对的是整个目标数据库.