C#反射在数据库操作中的应用(反射属性,反射字段)

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

现记录学习笔记

环境为:

  编译器: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}");

//......

posted @ 2021-07-24 18:50  初吻给了烟灬  阅读(585)  评论(0编辑  收藏  举报