下载本文代码:https://files.cnblogs.com/afritxia2008/WebTest.rar(请使用 Visual Studio 2008 打开)

  在进行讨论之前,我假设读者已经了解
.NET反射、自定义属性、CodeDom这些技术。并接触过ORM框架源码,如果对ORM并不了解,可以参考:
http://www.cnblogs.com/xdesigner/archive/2008/06/24/1228702.html。在这篇文章中,我们主要讨论通过CodeDom提高ORM读取数据的性能问题。

  ORMObject/Relation Mapping对象-关系数据库映射)其中的一个功能是将数据源数据赋值给实体。实现方法是利用自定义属性和.NET反射机制。例如:

 1使用CodeDom提高ORM性能    public class LWordEntity
 2    }


  DataColumn是自定义的属性类,代码并不复杂所以在这里也就省略了。接下来需要通过反射读取自定义属性,并赋值。代码如下:


 1使用CodeDom提高ORM性能    public void PutEntityProperties(object objEntity, DbDataReader dr)
 2


  以上代码实现了读取数据源数据并向实体赋值的功能。但这样做速度非常慢,因为每读取一条数据库记录,每读取一个数据字段并向实体赋值的时候,都必须进行一次反射操作。数据量越大,且数据字段或实体属性越多,那么速度就越慢!在以上代码中,对实体的反射操作,其目的就是赋值。可以被等价的语句所替代:
    
entity.Prop = dr[“Porp”];
用简单的赋值语句肯定要比反射的速度快很多,而大数据量和多数据库字段对其影响也不是很大。不过需要注意的是因为每一个实体的具体属性不相同,所以赋值过程也是不相同的。例如:
News实体赋值代码:

 1使用CodeDom提高ORM性能        void PutEntityProperties(NewsEntity entity, DbDataReader dr)
 2        }

 

User实体赋值代码:

 1使用CodeDom提高ORM性能        void PutEntityProperties(UserEntity entity, DbDataReader dr)
 2


  NewsUser所具备的属性不同,所以赋值过程,也不相同!但毫无疑问,使用直接赋值的方法是速度最快的!试想一下,假如在做反射的时候不是直接赋值,而是根据自定义属性,动态的生成赋值代码,编译以后临时保存起来。那么以后再进行赋值操作的时候,直接调用这个编译好的赋值代码,不就可以大大提升程序性能了么?有没有一个办法可以自动建立类似上面这样的代码呢?我们可以考虑使用反射和CodeDom技术。


使用CodeDom提高ORM性能


  首先为了解决不同实体的不同的赋值过程,我们需要建立一个接口:IEntityPropertyPutter。在该接口中的PutEntityProperties函数负责真正的赋值逻辑。在赋值的过程中会调用IEntityPropertyPutter的具体实现类的实例。具体类图如下:

 
使用CodeDom提高ORM性能

  EntityPropertyPutterFactory工厂类负责创建IEntityPropertyPutter接口具体实现类的实例。首先该工厂类会从缓存中获取IEntityPropertyPutter接口实例,如果该实例为空(还没有被创建),那么该工厂类会调用EntityPropertyPutterMaker构建者类创建实例(Entity实体类本身也可以直接实现IEntityPropertyPutter接口,来加快程序的运行速度)。在构建者内部会动态创建新的程序集(Assembly),在该程序集中只存在一个QuicklyPutter类。在QuicklyPutter类中描述了具体的赋值逻辑,这些逻辑编码则是根据反射和CodeDom完成的。最后交由CodeDom动态编译……根据不同的实体,所创建的程序集也不相同。所编译成功的程序集是临时存放在内存里,所以QuicklyPutter类用白色表示。具体代码如下:

 1使用CodeDom提高ORM性能using System;
 2使用CodeDom提高ORM性能using System.Collections.Generic;
 3使用CodeDom提高ORM性能using System.Data.Common;
 4使用CodeDom提高ORM性能using System.Reflection;
 5使用CodeDom提高ORM性能
 6使用CodeDom提高ORM性能using Net.AfritXia.Data.Mapping;
 7使用CodeDom提高ORM性能
 8使用CodeDom提高ORM性能namespace Net.AfritXia.Data
 9

 

设置器工厂类EntityPropertyPutterFactory:

 

 1使用CodeDom提高ORM性能using System;
 2使用CodeDom提高ORM性能using System.Collections;
 3使用CodeDom提高ORM性能using System.Reflection;
 4使用CodeDom提高ORM性能
 5使用CodeDom提高ORM性能namespace Net.AfritXia.Data
 6}

构建器EntityPropertyPutterMaker:

  1使用CodeDom提高ORM性能#undef _Debug  // 用于调试
  2使用CodeDom提高ORM性能
  3使用CodeDom提高ORM性能using System;
  4使用CodeDom提高ORM性能using System.CodeDom;
  5使用CodeDom提高ORM性能using System.Collections.Specialized;
  6使用CodeDom提高ORM性能using System.CodeDom.Compiler;
  7使用CodeDom提高ORM性能using System.Data.Common;
  8使用CodeDom提高ORM性能#if _Debug
  9使用CodeDom提高ORM性能using System.IO;
 10使用CodeDom提高ORM性能#endif
 11使用CodeDom提高ORM性能using System.Reflection;
 12使用CodeDom提高ORM性能
 13使用CodeDom提高ORM性能using Microsoft.CSharp;
 14使用CodeDom提高ORM性能
 15使用CodeDom提高ORM性能using Net.AfritXia.Data.Mapping;
 16使用CodeDom提高ORM性能
 17使用CodeDom提高ORM性能namespace Net.AfritXia.Data
 18}

代码时序图如下:

 
使用CodeDom提高ORM性能

具体代码可以参考:
Net.AfritXia.Data/IEntityPropertyPutter.cs
Net.AfritXia.Data/EntityPropertyPutterFactory.cs
Net.AfritXia.Data/EntityPropertyPutterMaker.cs
TestProj/UnitTest_Putter.cs(可以运行该测试文件)

相关文章: