[ORM]使用CodeDom提高ORM性能

使用CodeDom提高ORM性能

下载本文代码:http://www.cnblogs.com/Files/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    public class LWordEntity
 2    {
 3        /// <summary>
 4        /// 获取或设置留言 ID
 5        /// </summary>

 6        [DataColumn(ColumnName = "LWordUID")]
 7        public int LWordUID
 8        {
 9            // 
10        }

11
12        /// <summary>
13        /// 获取或设置发送用户
14        /// </summary>

15        [DataColumn(ColumnName = "PostUser")]
16        public string PostUser
17        {
18            // 
19        }

20
21        /// <summary>
22        /// 获取或设置发送时间
23        /// </summary>

24        [DataColumn(ColumnName = "PostTime")]
25        public DateTime PostTime
26        {
27            // 
28        }

29
30        /// <summary>
31        /// 获取或设置文本内容
32        /// </summary>

33        [DataColumn(ColumnName = "TextContent")]
34        public string TextContent
35        {
36            // 
37        }

38    }


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

 1    public void PutEntityProperties(object objEntity, DbDataReader dr)
 2    {
 3        // 获取实体类型
 4        Type objType = objEntity.GetType();
 5
 6        // 获取属性信息
 7        PropertyInfo[] propInfoList = objType.GetProperties();
 8
 9        if (propInfoList == null || propInfoList.Length <= 0)
10            return;
11
12        foreach (PropertyInfo propInfo in propInfoList)
13        {
14            object[] colAttrList = propInfo.GetCustomAttributes(typeof(DataColumnAttribute), false);
15
16            // 未标记 DataColumn 属性
17            if (colAttrList == null || colAttrList.Length <= 0)
18                continue;
19
20            // 获取数据列属性
21            DataColumnAttribute colAttr = colAttrList[0as DataColumnAttribute;
22
23            int ordinal = 1;
24
25            try
26            {
27                // 获取数据列序号
28                ordinal = dr.GetOrdinal(colAttr.ColumnName);
29            }

30            catch (Exception ex)
31            {
32                throw new MappingException(
33                    String.Format("{0} 未找到该数据列( Cannot Found this Column {0} )", colAttr.ColumnName), ex);
34            }

35
36            // 获取数据列值
37            object objValue = dr.GetValue(ordinal);
38
39            if (objValue is DBNull)
40            {
41                // 将 null 值设置到属性
42                propInfo.SetValue(objEntity, nullnull);
43            }

44            else
45            {
46                // 将值设置到属性
47                propInfo.SetValue(objEntity, objValue, null);
48            }

49        }

50    }

51


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

 1        void PutEntityProperties(NewsEntity entity, DbDataReader dr)
 2        {
 3            // 新闻 ID
 4            entity.ID = (int)dr["ID"];
 5            // 标题
 6            entity.Title = (string)dr["Title"];
 7            // 摘要
 8            entity.Summary = (string)dr["Summary"];
 9            // 发送用户
10            entity.PostUser = (string)dr["PostUser"];
11            // 发送时间
12            entity.PostTime = (DateTime)dr["PostTime"];
13            // 文本内容
14            entity.TextContent = (string)dr["TextContent"];
15        }

User实体赋值代码:

 1        void PutEntityProperties(UserEntity entity, DbDataReader dr)
 2        {
 3            // 用户 ID
 4            entity.ID = (int)dr["ID"];
 5            // 用户名称
 6            entity.UserName = (string)dr["UserName"];
 7            // 密码
 8            entity.UserPass = (string)dr["UserPass"];
 9            // 电子邮件
10            entity.EMail = (string)dr["EMail"];
11            // 注册时间
12            entity.RegisterTime = (DateTime)dr["RegisterTime"];
13        }

14

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

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

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

 1using System;
 2using System.Collections.Generic;
 3using System.Data.Common;
 4using System.Reflection;
 5
 6using Net.AfritXia.Data.Mapping;
 7
 8namespace Net.AfritXia.Data
 9{
10    partial class SQLHelper
11    {
12        public void PutEntityProperties<T>(T entity, DbDataReader dr) where T : class
13        {
14            // 获取设置器
15            IEntityPropertyPutter<T> putter = EntityPropertyPutterFactory.Create<T>(entity, this.IncludeDebugInformation);
16
17            if (putter == null)
18                throw new NullReferenceException(@"设置器为空( Null Putter )");
19
20            try
21            {
22                // 设置实体属性
23                putter.PutEntityProperties(entity, dr);
24            }

25            catch (Exception ex)
26            {
27                string errorMessage = null;
28                
29                // 定义异常信息格式
30                errorMessage = @"从数据库字段{0} 读取值并赋给属性{1} 时出错(实体类型: {2})";
31                // 格式化信息
32                errorMessage = String.Format(errorMessage, putter.CurrentDBColName, putter.CurrentPropName, putter.EntityTypeName);
33
34                // 抛出异常
35                throw new Exception(errorMessage, ex);
36            }

37        }

38    }

39}

40

 

设置器工厂类EntityPropertyPutterFactory:

 

 1using System;
 2using System.Collections;
 3using System.Reflection;
 4
 5namespace Net.AfritXia.Data
 6{
 7    /// <summary>
 8    /// 实体属性设置器工厂类
 9    /// </summary>

10    internal sealed class EntityPropertyPutterFactory
11    {
12        // 设置器字典
13        private static readonly Hashtable g_putterHash = Hashtable.Synchronized(new Hashtable());
14
15        /// <summary>
16        /// 创建实体属性设置器
17        /// </summary>
18        /// <typeparam name="T">实体类型模版</typeparam>
19        /// <param name="fromEntity">实体</param>
20        /// <param name="includeDebugInfo">是否包含调试信息</param>
21        /// <returns></returns>

22        public static IEntityPropertyPutter<T> Create<T>(T fromEntity, bool includeDebugInfo) where T : class
23        {
24            if (fromEntity == null)
25                return null;
26
27            // 如果实体本身已经实现了 IEntityPropertyPutter<T> 接口, 
28            // 则直接返回
29            if (fromEntity is IEntityPropertyPutter<T>)
30                return (IEntityPropertyPutter<T>)fromEntity;
31
32            IEntityPropertyPutter<T> putter = null;
33
34            // 获取字典关键字
35            string hashKey = fromEntity.GetType().FullName;
36
37            if (g_putterHash.ContainsKey(hashKey))
38            {
39                // 从字典中获取设置器
40                putter = g_putterHash[hashKey] as IEntityPropertyPutter<T>;
41            }

42            else
43            {
44                EntityPropertyPutterMaker maker = null;
45
46                // 创建构建器
47                maker = new EntityPropertyPutterMaker();
48                // 是否包含调试信息
49                maker.IncludeDebugInformation = includeDebugInfo;
50
51                // 新建应用程序集
52                putter = maker.Make<T>();
53                // 保存应用设置器到字典
54                g_putterHash.Add(hashKey, putter);
55            }

56
57            return putter;
58        }

59    }

60}

构建器EntityPropertyPutterMaker:

  1#undef _Debug  // 用于调试
  2
  3using System;
  4using System.CodeDom;
  5using System.Collections.Specialized;
  6using System.CodeDom.Compiler;
  7using System.Data.Common;
  8#if _Debug
  9using System.IO;
 10#endif
 11using System.Reflection;
 12
 13using Microsoft.CSharp;
 14
 15using Net.AfritXia.Data.Mapping;
 16
 17namespace Net.AfritXia.Data
 18{
 19    /// <summary>
 20    /// 构建实体属性设置器
 21    /// </summary>

 22    internal sealed class EntityPropertyPutterMaker
 23    {
 24        // 默认名称空间
 25        private const string DefaultNamespace = "Net.AfritXia.Data._AutoCode";
 26        // QuicklyPutter 类名称
 27        private const string QuicklyPutterClassName = "QuicklyPutter";
 28
 29        // 包含调试信息
 30        private bool m_includeDebugInfo = false;
 31
 32        类构造器
 40
 41        /// <summary>
 42        /// 设置或获取是否包含调试信息
 43        /// </summary>

 44        public bool IncludeDebugInformation
 45        {
 46            set
 47            {
 48                this.m_includeDebugInfo = value;
 49            }

 50
 51            get
 52            {
 53                return this.m_includeDebugInfo;
 54            }

 55        }

 56
 57        /// <summary>
 58        /// 构建实体属性设置器
 59        /// </summary>
 60        /// <typeparam name="T">实体类型模版</typeparam>
 61        /// <returns></returns>

 62        public IEntityPropertyPutter<T> Make<T>() where T : class
 63        {
 64            // 创建一个可编译的单元
 65            CodeCompileUnit compileUnit = this.MakeCompileUnit();
 66            // 创建名称空间
 67            CodeNamespace namespace_code = this.MakeNamespace();
 68            // 定义类
 69            CodeTypeDeclaration class_code = this.MakeClass<T>();
 70            // 创建 PutEntityProperties 方法
 71            CodeMemberMethod method_code = this.MakeMethod<T>();
 72
 73            // 添加方法到类
 74            class_code.Members.Add(method_code);
 75            // 添加类到名称空间
 76            namespace_code.Types.Add(class_code);
 77            // 添加名称空间到编译单元
 78            compileUnit.Namespaces.Add(namespace_code);
 79
 80            // 创建 C# 编译器
 81            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
 82            // 创建编译参数
 83            CompilerParameters options = new CompilerParameters();
 84
 85            // 添加对 System.dll 的引用
 86            options.ReferencedAssemblies.Add("System.dll");
 87            // 添加对 System.Data.dll 的引用
 88            options.ReferencedAssemblies.Add("System.Data.dll");
 89            // 添加对该项目的引用
 90            options.ReferencedAssemblies.Add(this.GetType().Assembly.Location);
 91            // 添加对实体项目的引用
 92            options.ReferencedAssemblies.Add(typeof(T).Assembly.Location);
 93            // 只在内存中编译
 94            options.GenerateInMemory = true;
 95
 96#if _Debug
 97            string srcFilePath = null;
 98
 99            srcFilePath = @"C:\{0}_{1}.cs";
100            srcFilePath = String.Format(srcFilePath, typeof(T).Name, QuicklyPutterClassName);
101
102            // 源文件输出流
103            StreamWriter srcOutput = new StreamWriter(srcFilePath, false);
104            // 写出源文件
105            provider.GenerateCodeFromCompileUnit(compileUnit, srcOutput, new CodeGeneratorOptions());
106
107            srcOutput.Flush();
108            srcOutput.Close();
109#endif
110
111            // 编译并获取编译结果
112            CompilerResults compileResult = provider.CompileAssemblyFromDom(options, compileUnit);
113
114            // 编译失败则抛出异常
115            if (compileResult.NativeCompilerReturnValue != 0)
116                throw new Exception("编译失败 ( Compile Failed )");
117
118            // 创建设置器
119            object putter = compileResult.CompiledAssembly.CreateInstance(DefaultNamespace + "." + QuicklyPutterClassName);
120
121            return (IEntityPropertyPutter<T>)putter;
122        }

123
124        /// <summary>
125        /// 构建可编译单元
126        /// </summary>
127        /// <returns></returns>

128        private CodeCompileUnit MakeCompileUnit()
129        {
130            // 创建一个可编译的单元
131            return new CodeCompileUnit();
132        }

133
134        /// <summary>
135        /// 构建名称空间
136        /// </summary>
137        /// <returns></returns>

138        private CodeNamespace MakeNamespace()
139        {
140            // 创建名称空间
141            return new CodeNamespace(DefaultNamespace);
142        }

143
144        /// <summary>
145        /// 构建 QuicklyPutter 类
146        /// </summary>
147        /// <returns></returns>

148        private CodeTypeDeclaration MakeClass<T>() where T : class
149        {
150            // 定义 QuicklyPutter 类
151            CodeTypeDeclaration class_code = new CodeTypeDeclaration(QuicklyPutterClassName);
152
153            // 令该类实现 IEntityPropertyPutter<T> 接口
154            class_code.BaseTypes.Add(typeof(IEntityPropertyPutter<T>));
155
156            // 添加 EntityTypeName 属性
157            class_code = this.MakeEntityTypeNameProperty<T>(class_code);
158            // 添加 CurrentPropName 属性
159            class_code = this.MakeCurrentPropNameProperty(class_code);
160            // 添加 CurrentDBColName 属性
161            class_code = this.MakeCurrentDBColNameProperty(class_code);
162
163            return class_code;
164        }

165
166        /// <summary>
167        /// 构建 EntityTypeName 属性
168        /// </summary>
169        /// <typeparam name="T">实体类型模版</typeparam>
170        /// <param name="targetClass">目标代码</param>
171        /// <returns></returns>

172        private CodeTypeDeclaration MakeEntityTypeNameProperty<T>(CodeTypeDeclaration targetClass) where T : class
173        {
174            if (targetClass == null)
175                throw new ArgumentNullException("targetClass");
176
177            /* 
178             * 以下代码将生成
179             * 
180             * public string EntityTypeName
181             * {
182             *     get
183             *     {
184             *         return 实体类型名称字符串
185             *     }
186             * }
187             * 
188             * 
189             */

190
191            // EntityTypeName 属性
192            CodeMemberProperty entityTypeNameProp_code = null;
193            
194            // 创建属性
195            entityTypeNameProp_code = new CodeMemberProperty();
196            // 定义为公共属性
197            entityTypeNameProp_code.Attributes = MemberAttributes.Public;
198            // 返回字符串类型
199            entityTypeNameProp_code.Type = new CodeTypeReference(typeof(string));
200            // 属性名称
201            entityTypeNameProp_code.Name = "EntityTypeName";
202            // 返回语句
203            entityTypeNameProp_code.GetStatements.Add(
204                new CodeMethodReturnStatement(new CodePrimitiveExpression(typeof(T).Name)));
205
206            // 添加属性到类
207            targetClass.Members.Add(entityTypeNameProp_code);
208
209            return targetClass;
210        }

211
212        /// <summary>
213        /// 构建 CurrentPropName 属性
214        /// </summary>
215        /// <param name="targetClass">目标类代码</param>
216        /// <returns></returns>

217        private CodeTypeDeclaration MakeCurrentPropNameProperty(CodeTypeDeclaration targetClass)
218        {
219            if (targetClass == null)
220                throw new ArgumentNullException("targetClass");
221
222            /* 
223             * 以下代码将生成
224             * 
225             * private string m_currPropName;
226             * 
227             * public string CurrentPropName 
228             * {
229             *     get
230             *     {
231             *         return this.m_currPropName;
232             *     }
233             * }
234             * 
235             */

236
237            // 变量名称
238            const string VaribleName = "m_currPropName";
239
240            // m_currPropName
241            CodeMemberField m_currPropName_code = null;
242
243            // 创建字段
244            m_currPropName_code = new CodeMemberField();
245            // 定义为私有成员
246            m_currPropName_code.Attributes = MemberAttributes.Private;
247            // 创建变量
248            m_currPropName_code = new CodeMemberField(typeof(string), VaribleName);
249
250            // 添加成员到类
251            targetClass.Members.Add(m_currPropName_code);
252
253            // CurrentPropName
254            CodeMemberProperty currPropName_code = null;
255            
256            // 创建属性
257            currPropName_code = new CodeMemberProperty();
258            // 定义为公共属性
259            currPropName_code.Attributes = MemberAttributes.Public;
260            // 返回字符串类型
261            currPropName_code.Type = new CodeTypeReference(typeof(string));
262            // 属性名称
263            currPropName_code.Name = "CurrentPropName";
264            // get 返回语句
265            currPropName_code.GetStatements.Add(
266                new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), VaribleName)));
267
268            // 添加属性到类
269            targetClass.Members.Add(currPropName_code);
270
271            return targetClass;
272        }

273
274        /// <summary>
275        /// 构建 CurrentDBColName 属性
276        /// </summary>
277        /// <param name="targetClass">父级类</param>
278        /// <returns></returns>

279        private CodeTypeDeclaration MakeCurrentDBColNameProperty(CodeTypeDeclaration targetClass)
280        {
281            if (targetClass == null)
282                throw new ArgumentNullException("targetClass");
283
284            /* 
285             * 以下代码将生成
286             * 
287             * private string m_currDBColName;
288             * 
289             * public string CurrentDBColName 
290             * {
291             *     get
292             *     {
293             *         return this.m_currDBColName;
294             *     }
295             * }
296             * 
297             */

298
299            // 变量名称
300            const string VaribleName = "m_currDBColName";
301            // m_currDBColName
302            CodeMemberField m_currDBColName_code = null;
303
304            // 创建字段
305            m_currDBColName_code = new CodeMemberField();
306            // 定义为私有成员
307            m_currDBColName_code.Attributes = MemberAttributes.Private;
308            // 创建变量
309            m_currDBColName_code = new CodeMemberField(typeof(string), VaribleName);
310
311            // 添加成员到类
312            targetClass.Members.Add(m_currDBColName_code);
313
314            // CurrentDBColName
315            CodeMemberProperty currDBCol_code = null;
316
317            // 创建属性
318            currDBCol_code = new CodeMemberProperty();
319            // 定义为公共属性
320            currDBCol_code.Attributes = MemberAttributes.Public;
321            // 返回字符串类型
322            currDBCol_code.Type = new CodeTypeReference(typeof(string));
323            // 属性名称
324            currDBCol_code.Name = "CurrentDBColName";
325            // get 返回语句
326            currDBCol_code.GetStatements.Add(
327                new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "m_currDBColName")));
328
329            // 添加属性到类
330            targetClass.Members.Add(currDBCol_code);
331
332            return targetClass;
333        }

334
335        /// <summary>
336        /// 构建 PutEntityProperties 方法
337        /// </summary>
338        /// <typeparam name="T"></typeparam>
339        /// <param name="fromEntity"></param>
340        /// <returns></returns>

341        private CodeMemberMethod MakeMethod<T>() where T : class
342        {
343            // PutObjectProperties 方法
344            CodeMemberMethod method_code = null;
345            
346            // 创建方法
347            method_code = new CodeMemberMethod();
348            // 定义为公共方法
349            method_code.Attributes = MemberAttributes.Public;
350            // 返回类型
351            method_code.ReturnType = new CodeTypeReference(typeof(void));
352            // 方法名称
353            method_code.Name = "PutEntityProperties";
354            // 添加参数 entity
355            method_code.Parameters.Add(new CodeParameterDeclarationExpression(typeof(T), "entity"));
356            // 添加参数 dr
357            method_code.Parameters.Add(new CodeParameterDeclarationExpression(typeof(DbDataReader), "dr"));
358
359            // 获取实体类型
360            Type objType = typeof(T);
361
362            // 获取 DataTable 属性标记
363            object[] tabAttrList = objType.GetCustomAttributes(typeof(DataTableAttribute), false);
364
365            if (tabAttrList == null || tabAttrList.Length <= 0)
366            {
367                throw new MappingException(
368                    String.Format(@"类 {0} 未标记 DataTable 属性 ( Unlabeled [DataTable] Attribute On Class {0} )", objType.Name));
369            }

370
371            // 获取属性信息
372            PropertyInfo[] propInfoList = objType.GetProperties();
373
374            if (propInfoList == null || propInfoList.Length <= 0)
375                return null;
376
377            foreach (PropertyInfo propInfo in propInfoList)
378            {
379                object[] colAttrList = propInfo.GetCustomAttributes(typeof(DataColumnAttribute), false);
380
381                // 未标记 DataColumn 属性
382                if (colAttrList == null || colAttrList.Length <= 0)
383                    continue;
384
385                // 获取数据列属性
386                DataColumnAttribute colAttr = colAttrList[0as DataColumnAttribute;
387
388                // 创建方法内容
389                method_code = this.MakeMethodContent(method_code, propInfo, colAttr, this.IncludeDebugInformation);
390            }

391
392            return method_code;
393        }

394
395        /// <summary>
396        /// 构建 PutEntityProperties 方法内容
397        /// </summary>
398        /// <param name="targetMethod"></param>
399        /// <param name="prop"></param>
400        /// <param name="attr"></param>
401        /// <param name="includeDebugInfo"></param>
402        /// <returns></returns>

403        private CodeMemberMethod MakeMethodContent(CodeMemberMethod targetMethod, PropertyInfo prop, DataColumnAttribute attr, bool includeDebugInfo)
404        {
405            if (targetMethod == null)
406                throw new ArgumentNullException("targetMethod");
407
408            if (attr == null)
409                throw new ArgumentNullException("attr");
410
411            // 实体变量名称 entity
412            string varEntityName = targetMethod.Parameters[0].Name;
413            // 数据源变量名称 dr
414            string varDrName = targetMethod.Parameters[1].Name;
415
416            // entity 属性名称
417            string varEntityPropName = String.Format(@"{0}.{1}", varEntityName, prop.Name);
418            // dr 属性名称
419            string varDrPropName = String.Format(@"{0}[""{1}""]", varDrName, attr.Name);
420
421            // 创建变量
422            CodeVariableReferenceExpression entityProp_code = new CodeVariableReferenceExpression(varEntityPropName);
423            // 创建值
424            CodeVariableReferenceExpression dr_code = new CodeVariableReferenceExpression(varDrPropName);
425
426            // 包含调试信息
427            if (includeDebugInfo)
428            {
429                // this.m_currPropName = entity.Prop
430                targetMethod.Statements.Add(new CodeAssignStatement(
431                    new CodeVariableReferenceExpression("this.m_currPropName"),
432                    new CodePrimitiveExpression(prop.Name)));
433
434                // this.m_currDBColName = attributeName
435                targetMethod.Statements.Add(new CodeAssignStatement(
436                    new CodeVariableReferenceExpression("this.m_currDBColName"),
437                    new CodePrimitiveExpression(attr.Name)));
438            }

439
440            if (attr.IsNullable)
441            {
442                /* 
443                 * 以下代码生成的是条件判断代码
444                 * 
445                 * if (dr[""] != DBNull.Value) {
446                 *     entity.Prop = dr[""];
447                 * }
448                 * 
449                 */

450
451                CodeConditionStatement if_code = new CodeConditionStatement();
452
453                // if (dr[""] != DBNull.Value)
454                if_code.Condition = new CodeBinaryOperatorExpression(
455                    new CodeVariableReferenceExpression(varDrPropName),
456                    CodeBinaryOperatorType.IdentityInequality,
457                    new CodeVariableReferenceExpression("System.DBNull.Value"));
458
459                // entity.Prop = dr[""];
460                if_code.TrueStatements.Add(new CodeAssignStatement(
461                    entityProp_code,
462                    new CodeCastExpression(prop.PropertyType, dr_code)));
463
464                targetMethod.Statements.Add(if_code);
465            }

466            else
467            {
468                // entity.Prop = dr[""];
469                targetMethod.Statements.Add(new CodeAssignStatement(
470                    entityProp_code,
471                    new CodeCastExpression(prop.PropertyType, dr_code)));
472            }

473
474            return targetMethod;
475        }

476    }

477}

代码时序图如下:

 

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

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏