最近接手了一个旧的系统,各种陈旧的问题比较多,其中最棘手的就是操作数据库的部分,具体如下:
1、核心库是一个最后修改时间为2008年的库,先不说有多陈旧,现在这个库只是一个DLL文件,没有源码,也已经没人知道里面都实现了些啥功能,就算你怀疑数据库读写有问题,也无法验证和调试,反编译出来的源码也没法用。
2、这个库用的是System.Data.OracleClient操作Oracle,问题很明显,依赖于Oracle客户端,区分32位和64位,一旦客户的Oracle客户端出点问题,系统就歇菜了,而且部署起来也不方便。
3、操作数据库用的全是拼写SQL语句,对我这种习惯了ORM的人,实在太痛苦了,而且对JSON和流数据的支持也不是很好,这两种数据都需要单独处理,无形中增加了操作数据库的次数。
明确了问题,也就知道了最终想要达到的效果,具体如下:
1、有源码,风险可控。
2、不依赖于Oracle客户端,不区分32位和64位,这个其实Oracle官方已经提供了解决方案,就是ODP.NET,最新版本已经快可以达到前面两个要求,而且提供了NUGET包,引用简单。
3、既要兼容旧有的DbHelper的操作方式,也要支持ORM的操作方式,一是因为原来代码量过大,不可能快速完全转到ORM,所以必须兼容旧有的操作方式,同时,ORM也是必须的,毕竟自己用着顺手。
知道了自己想要什么,于是,我就开始找可以做到这个库,功夫不负有心人,最终我找到了深蓝医生的SOD,完全满足我的要求,具体如下:
1、SOD完全开源,并提供使用指导。
2、SOD支持最新版本的ODP.NET,并提供了NUGET的获取方式,相当方便。
3、SOD不仅是一个ORM,还提供了DBHelper形式的数据库操作方式,不仅如此,更神奇的是,SOD支持执行SQL得到实体的操作方式,是不是很像Dapper.NET?
4、SOD支持现在大部分主流的数据库,以后要换库也是无缝对接。
5、客户反馈旧系统如果打开十几分钟没有操作,界面就会卡死,关了重新开,软件依然用不了,必须重启操作系统才能恢复正常,换了SOD之后,这个问题神奇的被修复了,看来真的是数据库读写有问题。不过也从侧面说明旧系统的异常处理和日志机制有些问题,这么严重的问题,既没有抛出异常,也没有记录日志,看来需要填的坑还是有一些的。
说了这么多废话,还是要来点干货,把我写的兼容旧系统的基于SOD的DbHelper给大家看看,写的不好,还希望多多指教,最后总结一句:
人生苦短,我用SOD,蜜!
1 using System; 2 using System.Collections.Generic; 3 using System.Data; 4 using Oracle.ManagedDataAccess.Client; 5 using PWMIS.DataMap.Entity; 6 using PWMIS.DataProvider.Adapter; 7 using PWMIS.DataProvider.Data; 8 9 namespace Db 10 { 11 /// <summary> 12 /// 数据库访问类 13 /// </summary> 14 public static class StaticDbHelper 15 { 16 private static AdoHelper _defaultDataBase; 17 18 /// <summary> 19 /// 获取或者设置默认的数据库操作对象,如果未设置将采用默认的配置进行实例化数据库操作对象。 20 /// 支持读写分离模式 21 /// </summary> 22 public static AdoHelper DefaultDataBase 23 { 24 get 25 { 26 var dataConInfomation = new DcicDbConnInfo(); 27 DcicComnLib.Sys_GetOracleSetting(ref dataConInfomation); 28 29 return _defaultDataBase ?? 30 MyDB.GetDBHelperByProviderString( 31 "PWMIS.DataProvider.Data.OracleDataAccess.Oracle,PWMIS.OracleClient", 32 $"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST={dataConInfomation.Ip})(PORT={dataConInfomation.Port})) (CONNECT_DATA=(SID={dataConInfomation.Sid})));User Id={dataConInfomation.UserId};Password={dataConInfomation.Pwd};"); 33 } 34 set { _defaultDataBase = value; } 35 } 36 37 #region ORM 38 39 /// <summary> 40 /// 获取查询结果数量 41 /// </summary> 42 /// <param name="goql"></param> 43 /// <returns></returns> 44 public static int Count<T>(GOQL<T> goql) where T : EntityBase, new() 45 { 46 return goql.ToList(DefaultDataBase).Count; 47 } 48 49 /// <summary> 50 /// 判断是否存在查询结果 51 /// </summary> 52 /// <param name="goql"></param> 53 /// <returns></returns> 54 public static bool Exists<T>(GOQL<T> goql) where T : EntityBase, new() 55 { 56 var count = Count(goql); 57 return count > 0; 58 } 59 60 /// <summary> 61 /// 增加一条记录 62 /// </summary> 63 /// <typeparam name="T"></typeparam> 64 /// <param name="model"></param> 65 /// <returns></returns> 66 public static bool Insert<T>(T model) where T : EntityBase, new() 67 { 68 var query = new EntityQuery<T>(DefaultDataBase); 69 var result = query.Insert(model); 70 71 return result == 1; 72 } 73 74 /// <summary> 75 /// 删除一条记录 76 /// </summary> 77 /// <typeparam name="T"></typeparam> 78 /// <param name="model"></param> 79 /// <returns></returns> 80 public static bool Delete<T>(T model) where T : EntityBase, new() 81 { 82 var query = new EntityQuery<T>(DefaultDataBase); 83 var result = query.Delete(model); 84 85 return result == 1; 86 } 87 88 /// <summary> 89 /// 更新一条记录 90 /// </summary> 91 /// <typeparam name="T"></typeparam> 92 /// <param name="model"></param> 93 /// <returns></returns> 94 public static bool Update<T>(T model) where T : EntityBase, new() 95 { 96 var query = new EntityQuery<T>(DefaultDataBase); 97 var result = query.Update(model); 98 99 return result == 1; 100 } 101 102 /// <summary> 103 /// 查询多条记录 104 /// </summary> 105 /// <typeparam name="T"></typeparam> 106 /// <param name="oql"></param> 107 /// <returns></returns> 108 public static List<T> QueryList<T>(GOQL<T> oql) where T : EntityBase, new() 109 { 110 return oql.ToList(DefaultDataBase); 111 } 112 113 /// <summary> 114 /// 查询一条记录 115 /// </summary> 116 /// <typeparam name="T"></typeparam> 117 /// <param name="oql"></param> 118 /// <returns></returns> 119 public static T QueryObject<T>(GOQL<T> oql) where T : EntityBase, new() 120 { 121 return oql.ToObject(DefaultDataBase); 122 } 123 124 #endregion 125 126 #region SQL TO ORM 127 128 /// <summary> 129 /// 查询多条记录 130 /// </summary> 131 /// <typeparam name="T"></typeparam> 132 /// <param name="sql"></param> 133 /// <returns></returns> 134 public static List<T> QueryList<T>(string sql) where T : EntityBase, new() 135 { 136 return EntityQuery<T>.QueryList(DefaultDataBase.ExecuteDataReader(sql)); 137 } 138 139 /// <summary> 140 /// 查询一条记录 141 /// </summary> 142 /// <typeparam name="T"></typeparam> 143 /// <param name="sql"></param> 144 /// <returns></returns> 145 public static T QueryObject<T>(string sql) where T : EntityBase, new() 146 { 147 return EntityQuery<T>.QueryObject(DefaultDataBase.ExecuteDataReader(sql)); 148 } 149 150 #endregion 151 152 #region SQL 153 154 /// <summary> 155 /// 获取DataTable 156 /// </summary> 157 /// <param name="sql"></param> 158 /// <returns></returns> 159 public static DataTable GetDataTable(string sql) 160 { 161 DataTable tableResult = null; 162 try 163 { 164 tableResult = DefaultDataBase.ExecuteDataSet(sql).Tables[0]; 165 } 166 catch 167 { 168 // ignored 169 } 170 return tableResult; 171 } 172 173 /// <summary> 174 /// 获取查询结果数量 175 /// </summary> 176 /// <param name="sql"></param> 177 /// <returns></returns> 178 public static int GetCount(string sql) 179 { 180 var count = 0; 181 try 182 { 183 var obj = DefaultDataBase.ExecuteScalar("select count(*) from ( " + sql + " )"); 184 count = Convert.ToInt32(obj); 185 } 186 catch 187 { 188 // ignored 189 } 190 return count; 191 } 192 193 /// <summary> 194 /// 执行SQL语句 195 /// </summary> 196 /// <param name="sql"></param> 197 /// <returns></returns> 198 public static bool Execute(string sql) 199 { 200 try 201 { 202 DefaultDataBase.ExecuteNonQuery(sql); 203 return true; 204 } 205 catch 206 { 207 return false; 208 } 209 } 210 211 /// <summary> 212 /// 判断是否存在查询结果 213 /// </summary> 214 /// <param name="sql"></param> 215 /// <returns></returns> 216 public static bool ExecuteCount(string sql) 217 { 218 var bok = false; 219 try 220 { 221 var count = GetCount(sql); 222 if (count > 0) 223 bok = true; 224 } 225 catch 226 { 227 // ignored 228 } 229 230 return bok; 231 } 232 233 /// <summary> 234 /// 返回数据表第一行、第一列的字段段值 235 /// </summary> 236 /// <param name="sql"></param> 237 /// <returns></returns> 238 public static string ExecuteString(string sql) 239 { 240 var result = ""; 241 try 242 { 243 result = (string)DefaultDataBase.ExecuteScalar(sql); 244 } 245 catch 246 { 247 // ignored 248 } 249 return result; 250 } 251 252 /// <summary> 253 /// 保存Blob 254 /// </summary> 255 /// <param name="cmdSql"></param> 256 /// <param name="keyName"></param> 257 /// <param name="myBytes"></param> 258 public static void SetBlob(string cmdSql, string keyName, byte[] myBytes) 259 { 260 var p = new OracleParameter(keyName, OracleDbType.Blob); 261 p.Value = myBytes; 262 DefaultDataBase.ExecuteNonQuery(cmdSql, CommandType.Text, new IDataParameter[] { p }); 263 } 264 265 /// <summary> 266 /// 获取Blob 267 /// </summary> 268 /// <param name="cmdSql"></param> 269 /// <returns></returns> 270 public static byte[] GetBlob(string cmdSql) 271 { 272 return (byte[])DefaultDataBase.ExecuteScalar(cmdSql); 273 } 274 275 #endregion 276 } 277 }