这几天学习反射的应用,今天把其应用到数据操作中

现记录学习笔记

环境为:

  编译器:vs2017

  数据库:access

  反射类型为:字段

1先在类文件的定义是用哪种数据库,和用字段还是属性来反射

本例是:Access数据库+反射字段

#define OLEDB_  //access数据库
#define FIELDS_  //反射字段

2.定义数据库操作类的别名,用来区分数据库操作要用的函数

定义是反射的是字段还是反射的是属性

    //区分是用哪种数据库
#if OLEDB_ //access
using MyConnection = OleDbConnection;
using MyCommand = OleDbCommand;
using MyDataAdapter = OleDbDataAdapter;
using MyCommandBuilder = OleDbCommandBuilder;
using MyParameter = OleDbParameter;
using MyDataRead = OleDbDataReader;
//...
#elif SQL_ //sql
using MyCommand = SqlCommand;
using MyConnectin = SqlConnection;
using MyDataAdapter = SqlDataAdapter;
using MyCommandBuilder = SqlCommandBuilder;
using MyParameter = SqlParameter;
using MyDataRead = SqlDataReader;
//.... #endif //区分是用类的字段还是类的属性,
#if FIELDS_
using MyInfo = FieldInfo;//字段
#elif POPRS_
using MyInfo = PropertyInfo;//属性 #endif

  

3.在类中定义方法来选择反射的样式

//单表模板操作类

//T 为和数据库中要操作的表一样的类或结构体

//可以反射属性,也可以反射字段

class BDAdo<T>

{

    /// <summary>
/// 获得属性列表,或是字段列表
/// </summary>
/// <returns></returns>
private MyInfo[] GetInfos()
{
#if FIELDS_ //字段
return typeof(T).GetFields();
#elif POPRS_ //属性
return typeof(T).GetProperties();
#endif
}

}

下面就是在类的各种操作的实现

4.获得查询结果的表

        /// <summary>
/// 查询指定条件的列表数据
/// </summary>
/// <param name="findsql"> 指定查询条件,为NULL就查询全部数据</param>
/// <returns></returns>
public DataTable GetDataTable(string findsql = null)//查询条件字符串,也就是Sql语句查询的 where 后面的条件语句
{
Type ty = typeof(T);
// string fName = string.Join(",", ty.GetFields().Select(p => p.Name));
string sql = $"select * from [{ty.Name}]";
if (findsql != null)
sql += $" where {findsql}"; DataTable dt = new DataTable();
conn = new MyConnection(conStr);
MyDataAdapter da = new MyDataAdapter(sql, conn); try
{
da.Fill(dt);
return dt;
}
finally
{
conn.Close();
da.Dispose();
}
}

5.添加数据

/// <summary>
/// 插入数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public bool InsertData(T t)
{
//获得对象的类型
Type ty = t.GetType(); //拼接添加数据的Sql语句
string intoSql = $"INSERT INTO [{ty.Name}] ({GetFildeNames()}) VALUES ({GetFileParams()})"; conn = new MyConnection(conStr);
MyCommand cmd = conn.CreateCommand();
cmd.CommandText = intoSql;
cmd.Parameters.AddRange(GetParameters(t)); try
{
conn.Open();
return cmd.ExecuteNonQuery() == 1;
}
finally
{
cmd.Dispose();
conn.Close();
}
}

6 根据字段或是属性获得参数化列表

        /// <summary>
/// 获得参数化列表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
private MyParameter[] GetParameters(T t)
{
Type ty = typeof(T);
List<MyParameter> parList = new List<MyParameter>();
foreach (var v in GetInfos())
{
MyParameter pr = new MyParameter($"@{v.Name}", v.GetValue(t));
parList.Add(pr);
}
return parList.ToArray();
}

7.获得字段或是属性名称组成的字符串

 /// <summary>
/// 获得类的字段名或属性名,组成的字符串
/// </summary>
/// <param name="ty"></param>
/// <returns></returns>
private string GetFildeNames()
{
Type ty = typeof(T);
return string.Join(",", GetInfos().Select(p => $"[{p.Name}]"));
}

样式:
name,sex,age,tel,adds

8.获得字段或是属性名称组成的参数格式字符串

 /// <summary>
/// 获得类的字段名或是属性名,并以参数化样式(@name)组成的字符串
/// </summary>
/// <param name="ty"></param>
/// <returns></returns>
private string GetFileParams()
{
Type ty = typeof(T);
return string.Join(",", GetInfos().Select(p => $"@{p.Name}"));
}
//样式:
@name,@sex,@age,@tel,@adds

9.对数据库的增,删,改,执行命令

1可以是Sql语句操作,

2也可以是参数化列表操作,

3也可以是储存过程操作

/// <summary>
/// Sql语句执行命令(insert,delete,update)
/// </summary>
/// <param name="sql"></param>
/// <param name="cmdType"></param>
/// <param name="pars"></param>
/// <returns></returns>
public int ExecuteNonQuery(string sql, CommandType cmdType = CommandType.Text,
params MyParameter[] pars)
{
conn = new MyConnection(conStr); MyCommand cmd = conn.CreateCommand();
cmd.CommandType = cmdType;
cmd.CommandText = sql;
if (pars.Length > 0)
{
cmd.Parameters.Clear();
cmd.Parameters.AddRange(pars);
} try
{
conn.Open();
return cmd.ExecuteNonQuery();
}
finally
{
conn.Close();
cmd.Dispose();
}
}

10.查询指定条件,返回一个对象实例

 /// <summary>
/// 查询指定条件的对象
/// </summary>
/// <param name="cxSql"></param>
/// <returns></returns>
public T FindOneObject(string cxSql)
{
Type ty = typeof(T);
//string sql = $"select {GetFildeNames()} from {ty.Name} where {cxSql}";
object obj = Activator.CreateInstance(ty);
DataTable dt = GetDataTable(cxSql);
if (dt.Rows.Count == 0)
return default(T); foreach (var v in GetInfos())
{ SetObjectValue(v, dt.Rows[0][$"{v.Name}"], ref obj);
}
return (T)obj;
}

SetObjectValue()

        /// <summary>
/// 设置字段或是属性相应的值
/// </summary>
/// <param name="v">属性或是字段</param>
/// <param name="value">要设置的值</param>
/// <param name="obj">要设置的对象</param>
private void SetObjectValue(MyInfo v, object value, ref object obj)
{
string name =null;//获得字段或是属性的数据类型名称,用来给相应的数据类型赋值
#if POPRS_ //属性
name = v.PropertyType.Name;
#elif FIELDS_ //字段
name=v.FieldType.Name;
#endif
switch (name)
{
case "Int32": //int
v.SetValue(obj, int.Parse(value.ToString()));
break; ; case "String": //string
v.SetValue(obj, value.ToString());
break; case "Double": //double
v.SetValue(obj, double.Parse(value.ToString()));
break; case "Object"://object
v.SetValue(obj, value);
break; case "Boolean"://bool
v.SetValue(obj, bool.Parse(value.ToString()));
break; case "Char"://char
v.SetValue(obj, char.Parse(value.ToString()));
break; case "Byte[]"://byte[]
if(value!=DBNull.Value)
v.SetValue(obj, (byte[])value);//强转为字节数组
break; default: //其他类型,以后用的时候再加上
throw new Exception("没有指定转换的类型!!!"); }
}

11.用法

在要用的类中声明一个静态对象

public class MyApp 
{
  public static BDAdo<TXL_TABLE> Ado { get => new BDAdo<TXL_TABLE>();/* set => ado = value;*/ }
}

示例1:添加数据

TXL_TABLE tt = new TXL_TABLE();
tt.ID = int.Parse(txtID.Text);
tt.TName = txtName.Text;
tt.Sex = txtSex.Text;
tt.Age=int.Parse(txtAge.Text);
tt.FenZu = txtFenZu.Text;
tt.Tel = txtTel.Text;
byte[] tem = { 0 };
if (picImage.Image != null)
tt.Image = MyApp.Ado.ImageToByte(picImage.Image);
else
tt.Image = tem; bool bRet = MyApp.Ado.InsertData(tt);
if(bRet)
{
MessageBox.Show("添加成功")
}

示例2:修改数据

TXL_TABLE tt = new TXL_TABLE();
tt.ID = int.Parse(txtID.Text);
tt.TName = txtName.Text;
tt.Sex = txtSex.Text;
tt.Age=int.Parse(txtAge.Text);
tt.FenZu = txtFenZu.Text;
tt.Tel = txtTel.Text;
byte[] tem = { 0 };
if (picImage.Image != null)
tt.Image = MyApp.Ado.ImageToByte(picImage.Image);
else
tt.Image = tem; if( MyApp.Ado.UpdateData($"ID={oldID}", tt)>0)
MessageBox.Show("修改成功");

示例3:查找单个对象

 int id = (int)Tag;
TXL_TABLE tt= MyApp.Ado.FindOneObject($"ID={id}");

//......

C#反射在数据库操作中的应用(反射属性,反射字段)的更多相关文章

  1. [转]C#反射,根据反射将数据库查询数据和实体类绑定,并未实体类赋值

    本文来自:http://www.cnblogs.com/mrchenzh/archive/2010/05/31/1747937.html /****************************** ...

  2. C#反射获取数据库字段

    static string sqlselect = "insert into {0}({1}) values ({2})"; (这个方法可以适用于任何数据库的插入语句) publi ...

  3. [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦

    [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...

  4. 反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性、字段),而不去使用Invoke方法)

    反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性.字段),而不去使用Invoke方法)   创建Delegate (1).Delegate.CreateDelegate(Type, ...

  5. 数据库操作中如何批量执行多个sql文件?

    数据库操作中如何批量执行多个sql文件? 1.应用场景:在历史数据导入过程中,会发现有很多个表形成的.sql文件,要是一个一个文件去手动执行,实在是费时间,所以采取以下方法. 2.将文件放在一定位置, ...

  6. 使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法

    使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法 效果展示 一个很简单的组件脚本 运行状态在Inspector面板可以随便修改字段和调用方法 方法调用日志 设计由来 最近在 ...

  7. @Retention(保留) 此注解用于运行时候(反射)时候使用 如果不使用的话 在反射时候无法获取到注解的值

    @Retention(保留) 此注解用于运行时候(反射)时候使用 如果不使用的话 在反射时候无法获取到注解的值

  8. 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】

    方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; priva ...

  9. Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理

    1.Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理 2. 自定义注解: 使用@interfac ...

  10. SQL批量更新数据库中所有用户数据表中字段类型为tinyint为int

    --SQL批量更新数据库中所有用户数据表中字段类型为tinyint为int --关键说明:--1.从系统表syscolumns中的查询所有xtype='48'的记录得到类型为[tinyint]的字段- ...

随机推荐

  1. ARM+DSP!全志T113-i+玄铁HiFi4开发板硬件说明书(1)

    前 言 本文档主要介绍开发板硬件接口资源以及设计注意事项等内容,测试板卡为全志T113-i+玄铁HiFi4开发板.由于篇幅问题,本篇文章共分为上下两集,点击账户可查看更多内容详情,开发问题欢迎留言,感 ...

  2. TI AM64x工业开发板硬件说明书(双核ARM Cortex-A53 + 单/四核Cortex-R5F + 单核Cortex-M4F,主频1GHz)

    前  言 本文主要介绍TL64x-EVM评估板硬件接口资源以及设计注意事项等内容. 创龙科技TL64x-EVM是一款基于TI Sitara系列AM64x双核ARM Cortex-A53 + 单/四核C ...

  3. spark内核架构深度剖析

  4. 【Python】用Python把从mysql统计的结果数据转成表格形式的图片并推送到钉钉群

    ** python把数据转为图片 / python推送图片到钉钉群 ** 需求:通过python访问mysql数据库,统计业务相关数据.把统计的结果数据生成表格形式的图片并发送到钉钉群里. 一:Cen ...

  5. 【ClickHouse】0:clickhouse学习3之时间日期函数

    官方文档: https://clickhouse.tech/docs/zh/sql-reference/functions/date-time-functions/ 常用的clickhouse时间函数 ...

  6. CF1591F 题解

    先不管值域,设计状态 \(dp_{i,j}\) 表示考虑前 \(i\) 个数最后一个数为 \(j\) 的方案数,那么有如下转移: \[dp_{i,j} = dp_{i-1,k} (j \not = k ...

  7. ubuntu16 安装 python-networkmanager 失败

    前言 ubuntu16 安装 python-networkmanager 失败 解决方案 sudo apt-get install libdbus-1-dev sudo apt-get install ...

  8. ubuntu20 python2 通过安装包安装mysql-python

    前言 众里寻他千百度,蓦然回首,那人却在灯火阑珊处. 最近要测试一个python2环境的代码,其中用到了MySQLdb, 查询网络,发现要安装mysql-python,于是就进行了一番艰难的探索,现在 ...

  9. Java高效率查询Mysql节点树数据

    示例 目前有一个功能:任务计划管理,必然存在多级子任务的父子级关系,每个任务还会存在其它数据的关联表. mysql无法一次性递归查出想要的数据结构,想必很多人都会是通过根目录递归查询数据库的方式查出树 ...

  10. Nginx常用操作

    Nginx Nginx的最重要的几个使用场景 静态资源服务,通过本地文件提供服务 反向代理服务,延伸出包括缓存,负载均衡等 API服务,OpenResty 相关概念 简单请求和非简单请求 请求方法是H ...