c#反射与泛型
解释都在注释里了,会不断更新
using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { public class DBHelper<T> where T : class, new() { //获取数据库连接名称(在appsettings.json配置文件下配置) private static string con = "Data Source=.;Initial Catalog=hahha;user=sa;password=010806wpz.;"; #region 查询 /// <summary> /// 查询 返回list泛型集合 /// </summary> /// <param name="where"></param> /// <returns></returns> public List<T> Query(string where) { DataTable tb = new DataTable(); List<T> list = new List<T>(); string sql = GetQuerySql(); sql += where; //将连接字符串赋值,获取到一个新实例 using (SqlConnection connection = new SqlConnection(con)) { //打开数据库的连接 connection.Open(); //实例化sqlcommand using (SqlCommand command = new SqlCommand(sql, connection)) { SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(command); sqlDataAdapter.Fill(tb); //获取T的类型 Type type = typeof(T); //循环行 for (int i = 0; i < tb.Rows.Count; i++) { //实例化T,每一次都需要实例化new 对象 //Activator.CreateInstance:使用指定类型的无参数构造函数创建指定类型的实例。 //参数:Type:要创建的对象类型 //返回值:一个对新创建对象的引用(一个新创建的对象)包含数据表的所有字段 Object obj = Activator.CreateInstance(type); for (int j = 0; j < tb.Columns.Count; j++) { //获取列的名称及类型 //tb.Columns[j].ColumnName代表每一列字段的名称(例如:ID,Name) //type.GetProperty:通过字段名称返回一个对象 //入参:要获取的属性名的字符串 //返回值(出参):返回符合指定要求的属性的对象(包括:字段类型,字段名称等)返回值类型为PropertyInfo PropertyInfo info = type.GetProperty(tb.Columns[j].ColumnName);//赋值 #region 类型的判断并赋值 //int类型 if (tb.Columns[j].DataType == typeof(Int32)) { //有没有可能空值? if (tb.Rows[i][j] != null) { //obj.setValue(info,12); int num = int.Parse(tb.Rows[i][j].ToString()); //info只是用作暂存 //SetValue方法:使用可选索引值设置指定对象的属性值 //参数: //第一个参数:要设置其属性值的对象。 //第二个参数:新的属性值。 info.SetValue(obj, int.Parse(tb.Rows[i][j].ToString()), null); //上面那一行代码的意思是:将obj对象中的属性挨个遍历赋值成对应的值 } else { //null值的情况 info.SetValue(obj, 0, null); } } //float类型 else if (tb.Columns[j].DataType == typeof(float)) { //有没有可能空值? if (tb.Rows[i][j] != null) { info.SetValue(obj, float.Parse(tb.Rows[i][j].ToString()), null); } else { //null值的情况 info.SetValue(obj, 0.0f, null); } } //datetime else if (tb.Columns[j].DataType == typeof(DateTime)) { //有没有可能空值? if (tb.Rows[i][j] != null) { info.SetValue(obj, DateTime.Parse(tb.Rows[i][j].ToString()), null); } else { //null值的情况 info.SetValue(obj, DateTime.Now, null); } } //double else if (tb.Columns[j].DataType == typeof(double)) { //有没有可能空值? if (tb.Rows[i][j] != null) { info.SetValue(obj, double.Parse(tb.Rows[i][j].ToString()), null); } else { //null值的情况 info.SetValue(obj, 0.00, null); } } //GUID else if (tb.Columns[j].DataType == typeof(Guid)) { //有没有可能空值? if (tb.Rows[i][j] != null && !tb.Rows[i][j].ToString().Equals("")) { info.SetValue(obj, Guid.Parse(tb.Rows[i][j].ToString()), null); } else { //null值的情况 info.SetValue(obj, Guid.Parse("00000000-0000-0000-0000-000000000000"), null); } } else { //string //有没有可能空值? if (tb.Rows[i][j] != null) { info.SetValue(obj, tb.Rows[i][j].ToString(), null); } else { //null值的情况 info.SetValue(obj, "", null); } } #endregion } //将object 类型强转对应的类型 //集合中添加这一条数据 list.Add((T)obj); } } } return list; } //拼接查询语句 public string GetQuerySql() { Type type = typeof(T); string sql = ""; //type.Name获取类的名称 sql = "select * from " + type.Name + " where 1=1 "; return sql; } #endregion #region 修改 public int Update(int Id, T model) { int flag = 0; //获取sql string sql = GetUpdateSql(Id,model); using (SqlConnection connection = new SqlConnection(con)) { connection.Open(); using (SqlCommand command = new SqlCommand(sql, connection)) { flag = command.ExecuteNonQuery(); } } return flag; } public string GetUpdateSql(int Id,T model) { string value = ""; //首先定义修改的字段及数据,只需一个变量即可,因为修改语句字段及值是在一块的,所以不需要定义键值对 //其次获取t所有的类型 //获取之后获取所有字段 //遍历保存了所有字段的数组 //判断传进来的字段不是id //判断每个字段值是否为空 //判断下标值+1是否等于当前的个数,等于的话就代表最后一个字段,不需要加, Type type = model.GetType(); PropertyInfo[] info= type.GetProperties(); for (int i = 0; i < info.Length; i++) { if (!info[i].Name.Contains("Id")) { if (info[i].GetValue(model) != null) { if (i + 1 == info.Length) { //在数据库中即使是int类型的也可以用两个单引号('')存储数据,datetime也是,所有就添加单引号 value += info[i].Name + "='" + info[i].GetValue(model) + "'"; } else { //因为字段不是单个,所以需要用,分割 value += info[i].Name + "='" + info[i].GetValue(model) + "',"; } } } } string sql = $"update {model.GetType().Name} set {value} where Id='{Id}'"; return sql; } #endregion #region 添加 public int Insert(T models) { int flag = 0; //获取sql string sql = GetInsertSql(models); using (SqlConnection connection = new SqlConnection(con)) { connection.Open(); using (SqlCommand command = new SqlCommand(sql, connection)) { flag = command.ExecuteNonQuery(); } } return flag; } public string GetInsertSql(T models) { //已实例化的实体用GetType,如果未实例化的我们需要使用typeof Type type = models.GetType();//new 过的对象 //获取所有的字段 PropertyInfo[] info = type.GetProperties(); //这里是字段 string field = ""; //获取值 string value = ""; //遍历所有的字段对象 for (int i = 0; i < info.Length; i++) { //info[i].GetValue(models)获取某个字段的属性值 //有可能字段没有值,没有值的我们不添加 //info[i]是一个抽象类,存储着第几个字段的名称及类型等 if (info[i].GetValue(models) != null) { if (!info[i].Name.Contains("Id")) //获取字段和值 if ((i + 1) == info.Length)//代表最后一个循环不要, { //info[i].Name代表某个字段的名称 field += info[i].Name; //因为GetValue的参数是object所以不需要用类型判断 string name = info[i].GetValue(models).ToString(); value += "'" + info[i].GetValue(models).ToString() + "'"; } else { field += info[i].Name + ","; value += "'" + info[i].GetValue(models).ToString() + "',"; } } } //生成了sql语句 string sql = "insert into " + type.Name + "(" + field + ") values(" + value + ")"; return sql; } #endregion #region 删除语句 public int Delete(T model) { string sql = GetDelete(model); int flag = 0; //数据库连接 using(SqlConnection conn=new SqlConnection(con)) { conn.Open(); //实例化对象 using (SqlCommand command=new SqlCommand(sql,conn)) { flag=command.ExecuteNonQuery(); } } return flag; } public string GetDelete(T model) { string id = ""; //删除和修改与添加基本无异 Type type = model.GetType(); PropertyInfo[] propertyInfo = type.GetProperties(); for (int i = 0; i < propertyInfo.Length; i++) { if (propertyInfo[i].GetValue(model)!=null) { if (propertyInfo[i].Name.Contains("Id")) { id += $"Id ={propertyInfo[i].GetValue(model)}"; } } } string sql = $"delete from {type.Name} where {id}"; return sql; } #endregion } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { public class Student { public int Id { get; set; } public string Name { get; set; } } }
using System; using System.Collections.Generic; namespace ConsoleApp1 { class Program { static void Main(string[] args) { DBHelper<Student> dBHelper = new DBHelper<Student>(); List<Student> list= dBHelper.Query(""); Console.WriteLine("查询语句:"); Console.WriteLine("数据量为:"+list.Count); Console.WriteLine("添加语句:"); Student student = new Student() { Id = 1, Name = "wxx" }; dBHelper.Insert(student); Console.WriteLine("修改语句:"); dBHelper.Update(student.Id, student); Console.WriteLine("修改语句执行成功!"); Console.WriteLine("删除语句:"); dBHelper.Delete(student); Console.WriteLine("删除成功!"); Console.ReadKey(); } } }
教大家一个小技巧:遇到没有用过的方法,接口,属性可以F12看看微软底层是如何解释的,当然微软底层是英文,可以利用翻译工具去翻译一下,看完一遍,仔细在自己脑袋里想几遍,要是还是不会,可以百度一下这个方法的用法.
一点点进步,一点点变优秀
转载于:https://blog.csdn.net/weixin_45978023/article/details/106780929
越是无知的人越是觉得自己无所不知(之前的自己)
越是学习的人越是觉得自己会的太少了(现在的自己)
共勉