C# 泛型和反射以及特性实现数据库增删查改

213 阅读1分钟

版本1:使用反射生成SQL语句并从SqlDataReader中读取数据

public T FindV1<T>(int id) where T : BaseModel
{
    Type type = typeof(T);
    string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));
    string sql = $"SELECT {columnString} FROM [{type.Name}] WHERE Id={id}";
    T t = (T)Activator.CreateInstance(type);
​
    using (SqlConnection conn = new SqlConnection(StaticConstant.SqlServerConnString))
    {
        SqlCommand command = new SqlCommand(sql, conn);
        conn.Open();
        SqlDataReader reader = command.ExecuteReader();
​
        if (reader.Read())
        {
            foreach (var prop in type.GetProperties())
            {
                prop.SetValue(t, reader[prop.Name] is DBNull ? null : reader[prop.Name]);
            }
        }
    }
​
    return t;
}

版本1中使用的技术:

  1. 反射:通过typeof(T)获取泛型类型TType对象,然后获取类型的属性并生成查询SQL语句。
  2. 特性:使用GetColumnName()方法从属性上获取特性,用于生成查询SQL语句中的列名。
  3. 反射:使用Activator.CreateInstance(type)创建泛型类型T的实例。
  4. 反射:遍历泛型类型T的属性,从SqlDataReader中读取数据并设置到实例的属性。

版本2:使用TSqlHelper生成SQL语句并使用ReaderToList方法

public T FindV2<T>(int id) where T : BaseModel
{
    string sql = $"{TSqlHelper<T>.FindSql}{id};";
    T t = null;
​
    using (SqlConnection conn = new SqlConnection(StaticConstant.SqlServerConnString))
    {
        SqlCommand command = new SqlCommand(sql, conn);
        conn.Open();
        SqlDataReader reader = command.ExecuteReader();
        List<T> list = this.ReaderToList<T>(reader);
        t = list.FirstOrDefault();
    }
​
    return t;
}

版本2中使用的技术:

  1. 泛型:使用泛型类TSqlHelper<T>生成查询SQL语句。
  2. 封装:使用ReaderToList<T>方法将SqlDataReader中的数据转换为泛型类型TList

两个版本的主要区别在于生成查询SQL语句和处理SqlDataReader的方式。版本1使用反射和特性生成SQL语句并从SqlDataReader中读取数据,而版本2则使用泛型类TSqlHelper生成SQL语句并调用ReaderToList方法处理SqlDataReader