C#反射入门-根据Ado游标对象创建List集合

C#反射入门-根据Ado游标对象创建List集合

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:

首先创建一个用于封装对应表数据的 Model 如下:

public class EUserInfo
{
    public int UserId { get; set; }
    public string UserCode { get; set; }
    public string UserName { get; set; }
    public string UserPwd { get; set; }
    public string Gender { get; set; }
    // 这里重写了 ToString,更直观的看到输出内容
    public override string ToString()
    {
        return "UserId:"+UserId+"|UserCode:"+UserCode+"|UserName:"+UserName+"|UserPwd:"+UserPwd+"|Gender:"+Gender;
    }
}

接下来创建 EUserInfo 实体类对应的表,这里我使用的是 SqlServer,对应 Sql 如下:

use master
go
if exists (select * from sys.databases where name='reflectDemoDB')
drop database reflectDemoDB
create database reflectDemoDB
go
use reflectDemoDB
go
create table UserInfo(
    UserId int primary key identity, 
    UserCode varchar(20) not null,
    UserName varchar(20) not null,
    UserPwd  varchar(20) not null,
    Gender   char(2) check(Gender in ('男','女'))
)
go
insert into UserInfo values('111111111','我体会过你的不完美。','123','男')
insert into UserInfo values('222222222','寂寞陪伴着','123','男')
insert into UserInfo values('333333333','偏执的眼眸︼╯','123','男')

为了操作 ADO 更便捷这里有一个简单的工具类:

/// <summary>
///DBHelper:数据库访问操作类
/// </summary>
public class DBHelper
{
    /// <summary>
    /// 更新操作:增,删,改 共用
    /// </summary>
    /// <param name="sql"></param>
    /// <returns>bool</returns>
    public static bool UpdateOpera(string sql,params SqlParameter[] sps)
    {
        SqlCommand cmd = new SqlCommand(sql, Connection);
        //////////////////将配置参数加入到Command中
        cmd.Parameters.AddRange(sps);
        /////////////////
        return cmd.ExecuteNonQuery() > 0;
    }

    /// <summary>
    /// 单个查询操作:返回首行首列数据
    /// </summary>
    /// <param name="sql">查询SQL语句</param>
    /// <returns>object</returns>
    public static object GetScalar(string sql, params SqlParameter[] sps)
    {
        SqlCommand cmd = new SqlCommand(sql, Connection);
        //////////////////将配置参数加入到Command中
        cmd.Parameters.AddRange(sps);
        /////////////////
        return cmd.ExecuteScalar();
    }

    /// <summary>
    /// 多行查询操作:返回SqlDataReader
    /// </summary>
    /// <param name="sql">查询SQL语句</param>
    /// <returns>SqlDataReader</returns>
    public static SqlDataReader GetReader(string sql, params SqlParameter[] sps)
    {
        SqlCommand cmd = new SqlCommand(sql, Connection);
        //////////////////将配置参数加入到Command中
        cmd.Parameters.AddRange(sps);
        /////////////////
        return cmd.ExecuteReader();
    }

    /// <summary>
    /// 多行查询操作:返回DataTable
    /// </summary>
    /// <param name="sql">查询SQL语句</param>
    /// <returns>DataTable</returns>
    public static DataTable GetDataTable(string sql, params SqlParameter[] sps)
    {
        DataTable dt = new DataTable();
        SqlDataAdapter dad = new SqlDataAdapter(sql, Connection);
        //////////////////将配置参数加入到Command中
        dad.SelectCommand.Parameters.AddRange(sps);
        /////////////////
        dad.Fill(dt);
        return dt;
    }

    public static List<string> GetColumnsByTableName(string tableName)
    {
        List<string> columnList = new List<string>();
        string sql = "select name from syscolumns where id=object_id(@tableName)";
        SqlDataReader sdr = GetReader(sql, new SqlParameter("@tableName", tableName));
        while (sdr.Read())
        {
            columnList.Add(sdr["name"].ToString());
        }
        sdr.Close();
        return columnList;
    }

    private static SqlConnection _connection;
    /// <summary>
    /// Connection对象
    /// </summary>
    public static SqlConnection Connection
    {
        get
        {
            string connectionString = "Data Source=.;Initial Catalog=reflectDemoDB;Integrated Security=True";
            if (_connection == null)
            {
                _connection = new SqlConnection(connectionString);
                _connection.Open();
            }
            else if (_connection.State == ConnectionState.Closed)
            {
                _connection.Open();
            }
            else if (_connection.State == ConnectionState.Broken || _connection.State == ConnectionState.Open)
            {
                _connection.Close();
                _connection.Open();
            }
            return _connection;
        }
    }
}

接下来就可以进入主题了,我这里使用一个 BaseDao 作为一个通用的 Dao 类,如下:

public class BaseDao<T>
{
    /// <summary>
    /// 获取泛型对应的实体类类名当做表名
    /// </summary>
    private static string TableName
    {
        get
        {
            return typeof(T).Name.Replace("E","");
        }
    }
    /// <summary>
    /// 获取泛型对应实体类所有属性
    /// </summary>
    private static PropertyInfo[] Properties { get { return typeof(T).GetProperties(); } }
    /// <summary>
    /// 通用查询所有方法
    /// </summary>
    /// <returns></returns>
    public List<T> GetAll()
    {
        //根据获取的表名拼装出sql语句
        string sql = "select * from " + TableName;
        SqlDataReader sdr = DBHelper.GetReader(sql);
        return CreateInstanceListOfSqlDataReader<T>(sdr);
    }
    private static T CreateInstance<T>(SqlDataReader sdr)
    {
        //或许泛型类所有属性

        //根据泛型T创建它的实例
        T t = (T)Activator.CreateInstance(typeof(T));
        //遍历该类所有属性
        foreach (PropertyInfo pro in Properties)
        {
            //判断属性类型 如果是对应类型就强转进行赋值
            if (pro.PropertyType.Equals(typeof(DateTime)))
                try
                {
                    pro.SetValue(t, Convert.ToDateTime(sdr[pro.Name]));//利用游标根据属性名获取对应列值给属性赋值
                }
                catch (Exception)
                {
                    throw new Exception("转换DateTime类型失败,[" + pro.Name + "]字段[value=" + sdr[pro.Name].ToString() + "]格式不正确");
                }
            else if (pro.PropertyType.Equals(typeof(int)))
                try
                {
                    pro.SetValue(t, Convert.ToInt32(sdr[pro.Name]));
                }
                catch (Exception)
                {
                    throw new Exception("转换int类型失败,[" + pro.Name + "]字段[value=" + sdr[pro.Name].ToString() + "]格式不正确");
                }
            else if (pro.PropertyType.Equals(typeof(double)))
                try
                {
                    pro.SetValue(t, Convert.ToDouble(sdr[pro.Name]));
                }
                catch (Exception)
                {
                    throw new Exception("转换Double类型失败,[" + pro.Name + "]字段[value=" + sdr[pro.Name].ToString() + "]格式不正确");
                }
            else
                pro.SetValue(t, sdr[pro.Name]);
        }
        return t;
    }
    /// <summary>
    /// 根据游标sdr创建一个所传类型对象集合并返回
    /// </summary>
    /// <typeparam name="T">泛型类型</typeparam>
    /// <param name="sdr">游标</param>
    /// <returns></returns>
    private List<T> CreateInstanceListOfSqlDataReader<T>(SqlDataReader sdr)
    {
        List<T> tList = new List<T>();
        while (sdr.Read())
        {
            T t = CreateInstance<T>(sdr);
            tList.Add(t);
        }
        return tList;
    }
}

接下来就可以使用这个通用的 Dao 类了,创建一个 UserInfoDao,来继承 BaseDao,如下:

public class UserInfoDao:BaseDao<EUserInfo>{}

测试:

class Program
{
    static void Main(string[] args)
    {
        UserInfoDao userInfoDao = new UserInfoDao();
        List<EUserInfo> userInfoList = userInfoDao.GetAll();
        foreach (EUserInfo userInfo in userInfoList)
        {
            Console.WriteLine(userInfo);
        }
        Console.ReadKey();
    }
}

这里我们可以直接调用 BaseDaoGetAll 方法,sql 会自动在 BaseDao 中帮我们拼装好,得到的结果如下:
image.png

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.zze.xyz/archives/csharp-reflect.html

Buy me a cup of coffee ☕.