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

现记录学习笔记

环境为:

  编译器: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. c/c++:带有返回类型的函数没有return语句会怎么样?

    c/c++:带有返回类型的函数没有return语句会怎么样 背景 机器有时候启动的时候发现异常,跟踪了代码发现,有人在写一个int函数的时候,有一个分支没有return: 参考:https://www ...

  2. HiAI Foundation开发平台,加速端侧AI应用的智能革命

    如果您是一名开发者,正在寻找一种高效.灵活且易于使用的端侧AI开发框架,那么HarmonyOS SDKHiAI Foundation服务(HiAI Foundation Kit)就是您的理想选择. 作 ...

  3. Webpack5

    Webpack是一款模块打包工具,可以把多个文件打包成一个或几个文件,它不仅能打包JS文件, 还能打包css, image等静态资源.当然,在默认情况下,它只打包JS文件和JSON文件,因为它只认识J ...

  4. Qt 学习笔记 - 第四章 - Qt的三驾马车之 - 网络编程

    Qt 学习笔记全系列传送门: Qt 学习笔记 - 第一章 - 快速开始.信号与槽 Qt 学习笔记 - 第二章 - 添加图片.布局.界面切换 Qt 学习笔记 - 第三章 - Qt的三驾马车之一 - 串口 ...

  5. Java Objects工具类重点方法使用

    Objects工具类 jdk 1.7引进的工具类,都是静态调用的方法,jdk 1.8新增了部分方法 重点方法 equals 用于字符串和包装对象的比较,先比较内存地址,再比较值 deepEquals ...

  6. Oracle 触发器 before insert update

    场景,往A表插入数据时,A表和B表是同一类型的状态下,A表中累计的值,不能超过B表中的值(注:往数据库插入时,不能批量执行事务!),利用触发器before insert update,监控状态,若超过 ...

  7. uBrand | 更适合个人创业者,小公司的AI品牌创建平台

    在跟一些辞职创业的朋友聊品牌,这个问题大家不约而同地都会提到:"我不会设计也没有资金请专业的设计师,有没有低成本打造品牌的方法呢?" 正好这段时间赶上AI的风潮,从众多AI工具中刚 ...

  8. 全网最适合入门的面向对象编程教程:08 类和对象的Python实现-@property装饰器:把方法包装成属性

    全网最适合入门的面向对象编程教程:08 类和对象的 Python 实现-@property 装饰器:把方法包装成属性 摘要: 本文主要对@property 装饰器的基本定义.使用场景和使用方法进行了介 ...

  9. yarn -D和-S区别

    -D和-S区别 安装的环境不同 -D是--save-dev的简写,会安装在开发环境中(production)中的devPendencies中 -S是--save的简写,会安装在生产环境中(develo ...

  10. 解决: Cannot load information for github.com

    问题在共享项目至idea时候出现:I am getting this error while sharing on GithHub in Intellije IDEA : Cannot load in ...