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

现记录学习笔记

环境为:

  编译器: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. 图最短路径之Dijkstra

    Dijkstra's shortest path algorithm 算法参考地址:Dijsktra's algorithm (geeksforgeeks.org) 算法的简介: 1)该算法用来计算最 ...

  2. Android ADB命令集锦

    Android ADB命令集锦 原文(有删改):https://blog.csdn.net/dianziagen/article/details/57400723 本文包括: adb基本指令 Shel ...

  3. Linux 驱动需要考虑的同步问题

    --- title: Linux 驱动需要考虑的同步问题 date: 2020-06-22 07:21:32 categories: tags: - ipc - linux - kernel - dr ...

  4. logo描边

  5. MySQL - CASE WHEN的高级用法

    Case语法 CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 WHEN conditionN THEN resultN E ...

  6. 基于Java网络书店商城设计实现(源码+lw+部署文档+讲解等)

    系统介绍: 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势:对于网络书店商城当然也不能排除在外,随着网络技术的不断成熟,带动了网络书店商城,它彻底改变了过去传统 ...

  7. JavaScript小面试~~JavaScript实现图片懒加载,多方式解决加载过多问题

    图片懒加载,就是滚动页面时,图片未出现在可视局域时不加载图片,只有图片出现在可视区域才加载. 思路:通过上面一段话,实现图片懒加载需要知道: 绑定滚动事件 可视窗口高度(VH) 图片元素距离可视局域顶 ...

  8. SQL 注入漏洞详解 - Union 注入

    1)漏洞简介 SQL 注入简介 SQL 注入 即是指 Web 应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在 Web 应用程序中事先定义好的查询语句的结尾上添加额外的 SQL 语句,在 ...

  9. Python版RNA-seq分析教程:DEseq2差异表达基因分析

    Bulk RNA-seq 分析的一个重要任务是分析差异表达基因,我们可以用 omicverse包 来完成这个任务.在omicverse中,除了最简单的ttest外,在这里,我们介绍一种类似R语言中的D ...

  10. nacos:关于注册服务与配置管理

    为什么要用nacos做配置中心? 1.nacos可以做到统一管理,而且在修改时可以做到动态管理,无需重启即可生效. 2.nacos通过namespace进行环境隔离, 约定: namespace:用于 ...