使用直接赋值的方法是速度最快的!试想一下,假如在做反射的时候不是直接赋值,而是根据自定义属性,动态的生成赋值代码,编译以后临时保存起来。那么以后再进行赋值操作的时候,直接调用这个编译好的赋值代码,不就可以大大提升程序性能了么?
下载本文代码: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读取数据的性能问题。
ORM(Object/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[0] as 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, null, null);
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
News与User所具备的属性不同,所以赋值过程,也不相同!但毫无疑问,使用直接赋值的方法是速度最快的!试想一下,假如在做反射的时候不是直接赋值,而是根据自定义属性,动态的生成赋值代码,编译以后临时保存起来。那么以后再进行赋值操作的时候,直接调用这个编译好的赋值代码,不就可以大大提升程序性能了么?有没有一个办法可以自动建立类似上面这样的代码呢?我们可以考虑使用反射和CodeDom技术。
首先为了解决不同实体的不同的赋值过程,我们需要建立一个接口:IEntityPropertyPutter。在该接口中的PutEntityProperties函数负责真正的赋值逻辑。在赋值的过程中会调用IEntityPropertyPutter的具体实现类的实例。具体类图如下:
EntityPropertyPutterFactory工厂类负责创建IEntityPropertyPutter接口具体实现类的实例。首先该工厂类会从缓存中获取IEntityPropertyPutter接口实例,如果该实例为空(还没有被创建),那么该工厂类会调用EntityPropertyPutterMaker构建者类创建实例(Entity实体类本身也可以直接实现IEntityPropertyPutter接口,来加快程序的运行速度)。在构建者内部会动态创建新的程序集(Assembly),在该程序集中只存在一个QuicklyPutter类。在QuicklyPutter类中描述了具体的赋值逻辑,这些逻辑编码则是根据反射和CodeDom完成的。最后交由CodeDom动态编译……根据不同的实体,所创建的程序集也不相同。所编译成功的程序集是临时存放在内存里,所以QuicklyPutter类用白色表示。具体代码如下:
1
using System;
2
using System.Collections.Generic;
3
using System.Data.Common;
4
using System.Reflection;
5
6
using Net.AfritXia.Data.Mapping;
7
8
namespace 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:
1
using System;
2
using System.Collections;
3
using System.Reflection;
4
5
namespace 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
3
using System;
4
using System.CodeDom;
5
using System.Collections.Specialized;
6
using System.CodeDom.Compiler;
7
using System.Data.Common;
8
#if _Debug
9
using System.IO;
10
#endif
11
using System.Reflection;
12
13
using Microsoft.CSharp;
14
15
using Net.AfritXia.Data.Mapping;
16
17
namespace 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
类构造器#region 类构造器
33
/**//// <summary>
34
/// 类默认构造器
35
/// </summary>
36
public EntityPropertyPutterMaker()
37
{
38
}
39
#endregion
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[0] as 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(可以运行该测试文件)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构