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

现记录学习笔记

环境为:

  编译器: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核心板规格书

    核心板简介 创龙科技SOM-TLT113是一款基于全志科技T113-i双核ARM Cortex-A7 + 玄铁C906 RISC-V + HiFi4 DSP异构多核处理器设计的全国产工业核心板,ARM ...

  2. 贝塞尔曲线原理、推导及Matlab实现

    贝塞尔曲线原理.推导及Matlab实现 贝塞尔曲线原理.推导及Matlab实现 一.简介 贝塞尔曲线提出 在数学的数值分析领域中,贝塞尔曲线(English:Bézier curve)是计算机图形学中 ...

  3. CF187D 题解

    模拟考最后一题是这道题,要是数组开大就场切了,最后不小心挂了 \(15\) 分. 以下是考场思路: 考虑这样一个问题,所有时间对 \(r+g\) 取余是可以的.毕竟红绿灯是一个循环. 再考虑这样一个东 ...

  4. podman+openresty+openssl,https双向认证demo测试

    前言 暂不讨论https原理,单论配置的话: 1. https单项认证 server: server.crt + server.key client: server_ca.crt 2. https双向 ...

  5. 树莓派4B-MAX9814麦克风模块

    树莓派4B-MAX9814麦克风模块 硬件需求 树莓派 MAX9814模块 杜邦线 MAX9814模块 电子特性 实验电路板 实验电路局部 典型工作特性 引角接线 代码展示 import RPi.GP ...

  6. 使用bootstrap-select 动态加载数据不显示的问题,级联数据置为空

    动态加载数据 $.showLoading('数据加载中');//开启遮挡层 $.ajax({ url: "/PickoutStock/GetSendReceive", data: ...

  7. 在宝塔上配置打包好的vue3项目

    配置文件如下 server{ listen 80; server_name gongchang.365cb.cn; index index.html index.htm default.php def ...

  8. [oeasy]python0132_[专业选修]utf-8_unicode_transformation_format_8_编码方式

    utf-8 回忆上次内容 上次再次输出了大红心<span style="color:red"></span> 找到了红心对应的编码 黑红梅方都对应有编码   ...

  9. Windows版本免费PyMol的安装

    技术背景 在前面一篇博客中,我们介绍过在Linux平台下安装和使用免费版本的PyMol.其实同样的这个免费版在Windows平台上(这里以win11为例)也是支持的. 安装流程 这个免费版本的PyMo ...

  10. 【微信小程序】05 设备信息 & 请求API

    获取系统信息(设备信息) https://developers.weixin.qq.com/miniprogram/dev/api/base/system/wx.getSystemInfo.html ...