使用ORM、反射、泛型书写通用的增删改查方法
来源:互联网 发布:php 数组长度 编辑:程序博客网 时间:2024/05/16 19:08
想做这个事情的原因:
公司因为升级系统的原因将WCF作为整个系统的中间部分,负责连接数据库传递数据的工作。而这个任务落到了我的头上。
在使用ORM(CHLOE)的过程中,发现一个问题,就是每一个表如果要实现增删改查的话都需要写一个相应的方法。这是一个重复到极点的工作,是我不能忍受的事情。于是想通过ORM实现通用型的增删改查工作,减轻负担。只需要增加表类,不需要增加SQL语句。
这个项目中我用的是chole
先订立一个目标:
增删改查都只需要写一个方法,增加ORM表类的同时立刻能够使用这几个方法完成增删改查的操作!
为了完成这个目标需要解决的问题:
1、如何在不知道类对象是什么的情况下获得属性的值;
2、如何做到传递一个类,让方法知道它的条件和更新字段;
3、如果做到更新时,只更新可以更新的属性
解决问题1:
使用反射获得对象类的属性和值,typeof().getpropertys()
解决问题2:
在类中增加两个List字段,一个存储Where属性,一个存储Update属性,类型为List
解决问题3:
增加一个在程序运行的过程中不变的字符串数组,存储可更新字段
解决的代码如下:
/// <summary> /// 所有表的基类,主要用来区分条件和更新的属性 /// </summary> public class TableBase { [JsonProperty]//让jsonconvert在执行转换的时候,转换这两个内部变量 private List<string> ListWhere { get { return _listW; } set { _listW = value; } }//保存条件的属性名称 private List<string> _listW = new List<string>(); [JsonProperty] private List<string> ListUpdate { get { return _listU; } set { _listU = value; } }//保存更改的属性名称 private List<string> _listU = new List<string>(); private int _isWhereOrUpdate = 0;//是否条件,为0既不是更新也不是条件 /// <summary> /// 设置接下来赋值的属性不写入_listWhere和_listUpdate /// </summary> public void SetNothing() { _isWhereOrUpdate = 0; } /// <summary> /// 设置接下来赋值的属性是条件 /// </summary> public void SetWhere() { _isWhereOrUpdate = 1; } /// <summary> /// 设置接下来赋值的属性是更新值 /// </summary> public void SetUpdate() { _isWhereOrUpdate = 2; } /// <summary> /// 返回条件属性队列 /// </summary> /// <returns></returns> public List<string> GetListWhere() { return ListWhere; } /// <summary> /// 返回更新属性队列 /// </summary> /// <returns></returns> public List<string> GetListUpdate() { return ListUpdate; } /// <summary> /// 将修改的数据增加到List中,注意此方法会将原来保存在LIST中的数据删除 /// </summary> /// <param name="value">属性名称</param> /// <param name="update">更新的列名</param> public void AddP(string value, string[] update) { for (int i = 0; i < ListUpdate.Count; i++)//时间复杂度O(2n-index) { if (ListUpdate[i] == value) { ListUpdate.RemoveAt(i); } } for (int i = 0; i < ListWhere.Count; i++)//时间复杂度O(2n-index) { if (ListWhere[i] == value) { ListWhere.RemoveAt(i); } } //添加数据到List中 if (_isWhereOrUpdate == 1) { ListWhere.Add(value); } else if (_isWhereOrUpdate == 2 && update != null && update.Contains(value)) //如果是能更新的字段 { ListUpdate.Add(value); } } /// <summary> /// 清空更新和条件队列 /// </summary> public void Clear() { ListWhere.Clear(); ListUpdate.Clear(); } /// <summary> /// 获得set方法所在的属性名称 /// 若使用release版本,frame.GetMethod()获取的是执行的方法,不会获取类中的方法。 /// release中会获取如TestSelect*()的方法,Debug获取SetProperity方法 /// </summary> /// <returns>返回属性名称</returns> public string GetPN() { StackTrace trace = new StackTrace(true); StackFrame frame = trace.GetFrame(1);//1代表上级,2代表上上级,以此类推 MethodBase method = frame.GetMethod(); //获得当前方法名称 //Console.WriteLine(memberName); try { var property = (from f in method.DeclaringType.GetProperties() where f.GetSetMethod() == method || f.GetGetMethod() == method select f).FirstOrDefault(); return property.Name; } catch { return null; } } }
上面的代码主要解决了获取属性名称、保存更新List和条件List的问题。能够更新的字段放在每一个Table表当中。
数据库表类结构如下图所示:
public class T_TRACK : TableBase { private static readonly string[] UPDATE = {"SFZMHM" };//能够更新的字段 public string SFZMHM { get { return _sfzmhm; } set { _sfzmhm = value; AddP(GetPN(), UPDATE); } } private string _sfzmhm; public string TESTDATE { get { return _testdate; } set { _testdate = value; AddP(GetPN(), UPDATE); } } private string _testdate; public int? KSCS { get { return _kscs; } set { _kscs = value; AddP(GetPN(), UPDATE); } } private int? _kscs; public string DATA { get { return _data; } set { _data = value; AddP(GetPN(), UPDATE); } } private string _data; }
上面的代码展示的是一个表的结构,其中UPDATE字段存储了此表可以由客户端更新的字段名称,如果为空的话表示客户端不能更新任何字段。
既然获得属性和值得问题解决了,那么现在就可以利用ORM和上面的TABLE内容写通用的更新代码了。如下:
/// <summary> /// 获得当前ListWhere或者ListUpdate的对象的属性 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="value"></param> /// <returns>返回PropertyInfo的列表</returns> private static List<PropertyInfo> GetPropertys<T>(T value, bool isWhere = true) where T : TableBase { //直接利用基类得到listStr List<string> ListPropertyStr = null; if (isWhere) ListPropertyStr = value.GetListWhere(); else ListPropertyStr = value.GetListUpdate(); //如果不能获得List的话,返回空 if (ListPropertyStr == null || ListPropertyStr.Count == 0) { return null; } //使用属性方法获得变量值,原来的方法是先获得所有属性,接着判断属性是否在listStr中 List<PropertyInfo> listProperty = new List<PropertyInfo>();//属性 for (int i = 0; i < ListPropertyStr.Count; i++) { listProperty.Add(typeof(T).GetProperty(ListPropertyStr[i])); } return listProperty; } /// <summary> /// 通用型数据更新方 /// </summary> /// <typeparam name="T">表类</typeparam> /// <param name="value">表类实体</param> /// <returns></returns> public static int UpdateData<T>(T value) where T : TableBase { List<PropertyInfo> listWhereP = GetPropertys(value); List<PropertyInfo> listUpdateP = GetPropertys(value, false); //如果没有相应的属性的话,返回空 if (listWhereP == null || listUpdateP == null || listWhereP.Count == 0 || listUpdateP.Count == 0) { return 0; } int updateRes = 0;//返回结果 //更新语句 try { OracleContext context = new OracleContext(new OracleConnectionFactory(GetConnectionStr())); //查询SQL语句与变量 DbParam[] paras = new DbParam[listWhereP.Count + listUpdateP.Count];//SQL变量保存的地方 //update string sql = "update " + typeof(T).Name + " set "; for (int i = 0; i < listUpdateP.Count - 1; i++) { sql += listUpdateP[i].Name + " = " + " :U" + i + ", "; paras[i] = DbParam.Create(":U" + i, listUpdateP[i].GetValue(value, null)); } sql += listUpdateP[listUpdateP.Count - 1].Name + " = " + " :U" + (listUpdateP.Count - 1) + " where "; paras[listUpdateP.Count - 1] = DbParam.Create(":U" + (listUpdateP.Count - 1), listUpdateP[listUpdateP.Count - 1].GetValue(value, null)); //where for (int i = 0; i < listWhereP.Count - 1; i++) { sql += listWhereP[i].Name + " = " + " :W" + i + " AND "; paras[i + listUpdateP.Count] = DbParam.Create(":W" + i, listWhereP[i].GetValue(value, null)); } sql += listWhereP[listWhereP.Count - 1].Name + " = " + " :W" + (listWhereP.Count - 1); paras[listWhereP.Count - 1 + listUpdateP.Count] = DbParam.Create(":W" + (listWhereP.Count - 1), listWhereP[listWhereP.Count - 1].GetValue(value, null)); //查询SQL语句的执行之处 updateRes = context.Session.ExecuteNonQuery(sql, paras); context.Dispose(); return updateRes; } catch (Exception ex) { LogHelper.WriteLogWcf(ex.Message, "UpdateData()"); throw new Exception(ex.Message); } }
比较遗憾的地方是通用型的方法依旧使用了SQL语句,并没有利用到ORM的易用性。但目前我还没有想到更符合更简洁的方案。
另外一点说明是关于TableBase类中SetWhere(),SetUpdate(),SetNothing()三个方法。
主要含义和命名方式一个意思,在使用了SetWhere()后,后面赋值的属性自动定义为条件,使用SetUpdate()后,后面赋值的属性定义为更新字段,SetNothing后,后面赋值的属性不做定义,主要用于写入数据。
调用的代码如下:
T_TRACK track=new T_TRACK();track.SetWhere();track.KSCS=2;track.SetUpdate();track.SFZMHM="1202222211111111233";UpdateData(track);
这就是通用性更新、查询、删除、插入的思路和方案。
- 使用ORM、反射、泛型书写通用的增删改查方法
- 增删改查-反射技术通用的方法
- 通用的增删改查方法(反射)附带MySQL数据库连接
- 学习笔记-泛型的使用:通用数据库增删改查
- 利用泛型、反射、JPA、Spring技术实现增删改查通用类
- 通用增删改查
- java使用反射实现对数据库的增删改查
- 基于jdbc 通用的增删改查
- 泛型的增删改查公共方法
- 使用轻量级ORM Dapper进行增删改查
- greenDao的使用---重点来啦 实现ORM连表 增删改查 颤抖吧凡人
- Java 利用反射、泛型实现dao层的增删改查
- don4j演示---增删改查以及无中生有方法的使用
- dao实现层通用增删改查方法
- Sql反射增删查改
- 反射技术------增删改查
- jdbc 增删改的通用方法
- 基于Spring+Hibernate的通用增删改查的实现方法
- squid代理及加速(理论加案例篇)
- 雨巷
- KMP 算法(1):如何理解 KMP 讲得特别好
- Python在pycharm中的调试(debug)
- JS中const,var,let区别
- 使用ORM、反射、泛型书写通用的增删改查方法
- css ico box-sizing 单行不换行省略
- jquery获取select标签选中的值
- 在Editplus中,如何集成javac和java两种命令
- ffmpeg
- 时隔好久,终于又要开始了,因为内容比较繁杂,不得不开始写下去。
- [BZOJ]3940: [Usaco2015 Feb]Censoring AC自动机
- 牛顿法计算平方根-Python
- Python Learning