C#连接Oracle数据库返回DataRead后,用DynamicMethod转换成实体,其中整形转换出错,其他类型正常

高彬 2017-10-12 07:06:33
为了提高dataRead转换实现的性能,避免代码重复,我使用了DynamicMethod动态创建一个方法,我的开发语言是C#,但是其中int型的属性转换为实体后值有错误,在dataRead中查看是正确的,比如:
实体是:

public class test{
public int ID{set;get;}
public string NAME{get;set;}
}

连接数据库返回DataRead对象是:


OracleDataReader read = ……;//连接数据库获取数据的代码我就省略,大家都会!
/*如果在这里查看read中ID的值是正确的,假如数据库里的值为1,这里查看值也是1 */
//转换为对应的实体集合(DataToList在下面贴出了代码)
List<test> list = DataToList.ReadToList<test>(read);
//就在这里list中ID的值已经不是1了,还是一个其他数字,有的项目中显未为360,有的显示为512,暂时不明白为什么

经过多次调试发现除了int型的转换有问题,其他数据类型的转换正常,所以问题可能就出在数据类型转换上,但是具体怎么解决暂时不知道,我只能换数据类型!!另外用ms sql server数据库测试不存在此问题,希望高手能指明原因!!!!!

下面贴出由OracleDataReader转换为实现的代码:

/// <summary>
/// IDataReader数据转换成List类
/// </summary>
public static class DataToList
{
/// <summary>
/// IDataReader数据转换成List方法
/// </summary>
/// <typeparam name="TResult">返回Model类型</typeparam>
/// <param name="dr">IDataReader数据</param>
/// <param name="isClose">是否关闭 DataReader</param>
/// <returns>转换结果</returns>
public static List<TResult> ReadToList<TResult>(this IDataReader dr, bool isClose=true) where TResult : class, new()
{

IDataReaderDynamicEntityBuilder<TResult> eblist = IDataReaderDynamicEntityBuilder<TResult>.CreateBuilder(dr);
List<TResult> list = new List<TResult>();
if (dr == null)
{
return list;
}
while (dr.Read())
{
list.Add(eblist.Build(dr));
}

if (isClose)
{
dr.Close();
dr.Dispose(); dr = null;
}

return list;

}

}



/// <summary>
///创建实体
/// </summary>
/// <typeparam name="T"></typeparam>
public class IDataReaderDynamicEntityBuilder<T>
{
//私有构造函数
private IDataReaderDynamicEntityBuilder() { }

private static readonly MethodInfo getValueMethod = typeof(IDataRecord).GetMethod(
"get_Item",
new Type[] { typeof(int) }
);
private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod(
"IsDBNull",
new Type[] { typeof(int) });

//委托
private delegate T Load(IDataRecord dataRecord);

//最终执行动态方法的一个委托 参数是IDataRecord接口
private Load handler;


/// <summary>
/// 使用委托调用已经构造好的动态方法
/// </summary>
/// <param name="dataRecord"></param>
/// <returns></returns>
public T Build(IDataRecord dataRecord)
{
//执行CreateBuilder里创建的DynamicCreate动态方法的委托
return handler(dataRecord);
}


/// <summary>
/// 构造实现类的动态方法
/// </summary>
/// <param name="dataRecord"></param>
/// <returns></returns>
public static IDataReaderDynamicEntityBuilder<T> CreateBuilder(IDataRecord dataRecord)
{
IDataReaderDynamicEntityBuilder<T> dynamicBuilder = new IDataReaderDynamicEntityBuilder<T>();

//定义一个名为DynamicCreate的动态方法,返回值typof(T),参数typeof(IDataRecord)
DynamicMethod method = new DynamicMethod("DynamicCreate",
typeof(T), //返回值类型
new Type[] { typeof(IDataRecord) },//参数
typeof(T),
true);

//创建一个MSIL生成器,为动态方法生成代码
ILGenerator generator = method.GetILGenerator();

//声明指定类型的局部变量 可以 T result 这么理解
LocalBuilder result = generator.DeclareLocal(typeof(T));
//BindingFlags.IgnoreCase |
//BindingFlags.Public |
//BindingFlags.Instance);

//实例化类型的对象,并将其存储在本地变量(result). 可以 result=new T();这么理解
generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
generator.Emit(OpCodes.Stloc, result);

//数据集合
for (int i = 0; i < dataRecord.FieldCount; i++)
{
//根据列名取属性 原则上属性和列是一一对应的关系
PropertyInfo propertyInfo = typeof(T).GetProperty(dataRecord.GetName(i));

Label endIfLabel = generator.DefineLabel();

if (propertyInfo != null && propertyInfo.GetSetMethod() != null)//实体存在该属性 且该属性有SetMethod方法
{

generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldc_I4, i);
//调用IsDBNull方法 如果IsDBNull == true contine
generator.Emit(OpCodes.Callvirt, isDBNullMethod);
generator.Emit(OpCodes.Brtrue, endIfLabel);

/*如果在read中此值非null,则在对象 中设置此值*/
generator.Emit(OpCodes.Ldloc, result);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldc_I4, i);

//调用get_Item方法
generator.Emit(OpCodes.Callvirt, getValueMethod);

//拆箱操作 问题可能就在这里
generator.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(i));
// generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
//给该属性设置对应值
generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());

generator.MarkLabel(endIfLabel);
}
}

/*给本地变量(result)返回值*/
generator.Emit(OpCodes.Ldloc, result);
generator.Emit(OpCodes.Ret);//方法结束,返回

//完成动态方法的创建,并且创建执行该动态方法的委托,赋值到全局变量handler,handler在Build方法里Invoke
dynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load));
return dynamicBuilder;
}
}
...全文
499 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
高彬 2017-10-13
  • 打赏
  • 举报
回复
引用 3 楼 duanzi_peng 的回复:
属性转换为实体后值有错误, -》什么错误,倒是贴出来呀
楼主在第二段代码里已经说出了问题,并不是说程序报错了:

OracleDataReader  read = ……;//连接数据库获取数据的代码我就省略,大家都会!
/*如果在这里查看read中ID的值是正确的,假如数据库里的值为1,这里查看值也是1 */
 //转换为对应的实体集合(DataToList在下面贴出了代码)
 List<test> list = DataToList.ReadToList<test>(read);
//就在这里list中ID的值已经不是1了,还是一个其他数字,有的项目中显未为360,有的显示为512
qq_40608940 2017-10-13
  • 打赏
  • 举报
回复
数据类型对应好就可以了:数据库里 NUMBER(p) <=p<=19 对应C# 类型:Int64,NUMBER(p)<=p<=9 对应:Int32
  • 打赏
  • 举报
回复
属性转换为实体后值有错误, -》什么错误,倒是贴出来呀
高彬 2017-10-13
  • 打赏
  • 举报
回复
找到了答案,原来是数据库该字段设置的数据范围大,程序中用了一个较小的数据类型导致的此问题!!!
高彬 2017-10-12
  • 打赏
  • 举报
回复
微信和其他移动端csdn做的很差,所以建议在pc端浏览!
【SCI复现】含可再生能源与储能的区域微电网最优运行:应对不确定性的解鲁棒性与非预见性研究(Matlab代码实现)内容概要:本文围绕含可再生能源与储能的区域微电网最优运行展开研究,重点探讨应对不确定性的解鲁棒性与非预见性策略,通过Matlab代码实现SCI论文复现。研究涵盖多阶段鲁棒调度模型、机会约束规划、需求响应机制及储能系统优化配置,结合风电、光伏等可再生能源出力的不确定性建模,提出兼顾系统经济性与鲁棒性的优化运行方案。文中详细展示了模型构建、算法设计(如C&CG算法、大M法)及仿真验证全过程,适用于微电网能量管理、电力系统优化调度等领域的科研与工程实践。; 适合人群:具备一定电力系统、优化理论和Matlab编程基础的研究生、科研人员及从事微电网、能源管理相关工作的工程技术人员。; 使用场景及目标:①复现SCI级微电网鲁棒优化研究成果,掌握应对风光负荷不确定性的建模与求解方法;②深入理解两阶段鲁棒优化、分布鲁棒优化、机会约束规划等先进优化方法在能源系统中的实际应用;③为撰写高水平学术论文或开展相关课题研究提供代码参考和技术支持。; 阅读建议:建议读者结合文档提供的Matlab代码逐模块学习,重点关注不确定性建模、鲁棒优化模型构建与求解流程,并尝试在不同场景下调试与扩展代码,以深化对微电网优化运行机制的理解。
个人防护装备实例分割数据集 一、基础信息 数据集名称:个人防护装备实例分割数据集 图片数量: 训练集:4,524张图片 分类类别: - Gloves(手套):工作人员佩戴的手部防护装备。 - Helmet(安全帽):头部防护装备。 - No-Gloves(未戴手套):未佩戴手部防护的状态。 - No-Helmet(未戴安全帽):未佩戴头部防护的状态。 - No-Shoes(未穿安全鞋):未佩戴足部防护的状态。 - No-Vest(未穿安全背心):未佩戴身体防护的状态。 - Shoes(安全鞋):足部防护装备。 - Vest(安全背心):身体防护装备。 标注格式:YOLO格式,包含实例分割的多边形坐标和类别标签,适用于实例分割任务。 数据格式:来源于实际场景图像,适用于计算机视觉模型训练。 二、适用场景 工作场所安全监控系统开发:数据集支持实例分割任务,帮助构建能够自动识别工作人员个人防护装备穿戴状态的AI模型,提升工作环境安全性。 建筑与工业安全检查:集成至监控系统,实时检测PPE穿戴情况,预防安全事故,确保合规性。 学术研究与创新:支持计算机视觉在职业安全领域的应用研究,促进AI与安全工程的结合。 培训与教育:可用于安全培训课程,演示PPE识别技术,增强员工安全意识。 三、数据集优势 精准标注与多样性:每个实例均用多边形精确标注,确保分割边界准确;覆盖多种PPE物品及未穿戴状态,增加模型鲁棒性。 场景丰富:数据来源于多样环境,提升模型在不同场景下的泛化能力。 任务适配性强:标注兼容主流深度学习框架(如YOLO),可直接用于实例分割模型开发,支持目标检测和分割任务。 实用价值高:专注于工作场所安全,为自动化的PPE检测提供可靠数据支撑,有助于减少工伤事故。

111,120

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧