最近接手了一个旧的系统,各种陈旧的问题比较多,其中最棘手的就是操作数据库的部分,具体如下:
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,蜜!
SOD源码地址:
OSC@GIT:http://git.oschina.net/dxzyx/SOD
Codeplex:http://pwmis.codeplex.com/SourceControl/latest
GITHUB:https://github.com/znlgis/PDF.NET-SOD
NUGET地址:https://www.nuget.org/profiles/znlgis
1 using System.Collections.Generic; 2 using PWMIS.DataMap.Entity; 3 using PWMIS.DataProvider.Adapter; 4 using PWMIS.DataProvider.Data; 5 6 namespace ComnLib 7 { 8 /// <summary> 9 /// 数据库访问类 10 /// </summary> 11 public class DbHelper 12 { 13 #region 静态部分 14 15 private static AdoHelper _instance; 16 /// <summary> 17 /// 获取或者设置默认的数据库操作对象,如果未设置将采用默认的配置进行实例化数据库操作对象。 18 /// 支持读写分离模式 19 /// </summary> 20 public static AdoHelper Instance 21 { 22 get 23 { 24 if (_instance == null) 25 { 26 var dataConInfomation = new DcicDbConnInfo(); 27 DcicComnLib.Sys_GetOracleSetting(ref dataConInfomation); 28 29 _instance = 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 35 return _instance; 36 } 37 } 38 39 /// <summary> 40 /// 增加一条记录 41 /// </summary> 42 /// <typeparam name="T"></typeparam> 43 /// <param name="model"></param> 44 /// <returns></returns> 45 public static bool Insert<T>(T model) where T : EntityBase, new() 46 { 47 var query = new EntityQuery<T>(Instance); 48 var result = query.Insert(model); 49 50 return result == 1; 51 } 52 53 /// <summary> 54 /// 执行一个无返回值的OQL语句 55 /// </summary> 56 /// <param name="oql"></param> 57 /// <returns></returns> 58 public static bool ExecuteOql(OQL oql) 59 { 60 var result = EntityQuery.ExecuteOql(oql, Instance); 61 return result == 1; 62 } 63 64 /// <summary> 65 /// 删除一条记录,必须有主键 66 /// </summary> 67 /// <typeparam name="T"></typeparam> 68 /// <returns></returns> 69 public static bool Delete<T>(T model) where T : EntityBase, new() 70 { 71 var query = new EntityQuery<T>(Instance); 72 var result = query.Delete(model); 73 74 return result == 1; 75 } 76 77 /// <summary> 78 /// 更新一条记录,必须有主键 79 /// </summary> 80 /// <typeparam name="T"></typeparam> 81 /// <returns></returns> 82 public static bool Update<T>(T model) where T : EntityBase, new() 83 { 84 var query = new EntityQuery<T>(Instance); 85 var result = query.Update(model); 86 87 return result == 1; 88 } 89 90 /// <summary> 91 /// 使用OQL查询多条记录 92 /// </summary> 93 /// <typeparam name="T"></typeparam> 94 /// <param name="oql"></param> 95 /// <returns></returns> 96 public static List<T> QueryList<T>(OQL oql) where T : EntityBase, new() 97 { 98 var query = new EntityQuery<T>(Instance); 99 return query.GetList(oql); 100 } 101 102 /// <summary> 103 /// 使用GOQL查询多条记录 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(Instance); 111 } 112 113 /// <summary> 114 /// 使用OQL查询一条记录 115 /// </summary> 116 /// <typeparam name="T"></typeparam> 117 /// <param name="oql"></param> 118 /// <returns></returns> 119 public static T QueryObject<T>(OQL oql) where T : EntityBase, new() 120 { 121 var query = new EntityQuery<T>(Instance); 122 123 return query.GetObject(oql); 124 } 125 126 /// <summary> 127 /// 使用GOQL查询一条记录 128 /// </summary> 129 /// <typeparam name="T"></typeparam> 130 /// <param name="oql"></param> 131 /// <returns></returns> 132 public static T QueryObject<T>(GOQL<T> oql) where T : EntityBase, new() 133 { 134 return oql.ToObject(Instance); 135 } 136 137 /// <summary> 138 /// 使用SQL查询多条记录 139 /// </summary> 140 /// <typeparam name="T"></typeparam> 141 /// <param name="sql"></param> 142 /// <returns></returns> 143 public static List<T> QueryList<T>(string sql) where T : EntityBase, new() 144 { 145 return EntityQuery<T>.QueryList(Instance.ExecuteDataReader(sql)); 146 } 147 148 /// <summary> 149 /// 使用SQL查询一条记录 150 /// </summary> 151 /// <typeparam name="T"></typeparam> 152 /// <param name="sql"></param> 153 /// <returns></returns> 154 public static T QueryObject<T>(string sql) where T : EntityBase, new() 155 { 156 return EntityQuery<T>.QueryObject(Instance.ExecuteDataReader(sql)); 157 } 158 159 /// <summary> 160 /// 用于复杂查询的映射 161 /// </summary> 162 /// <param name="sql"></param> 163 /// <returns>实体数据容器</returns> 164 public static DataReaderMapper QueryMapper(string sql) 165 { 166 return Instance.ExecuteMapper(sql); 167 } 168 169 #endregion 170 171 #region 动态部分 172 173 /// <summary> 174 /// 获取各种数据库的DbHelper 175 /// </summary> 176 /// <param name="providerName"></param> 177 /// <param name="connectionString"></param> 178 /// <returns></returns> 179 public AdoHelper GetHelper(string providerName, string connectionString) 180 { 181 return MyDB.GetDBHelperByProviderString(providerName, 182 connectionString); 183 } 184 185 /// <summary> 186 /// 获取Oracle数据库的DbHelper 187 /// </summary> 188 /// <param name="dataConInfomation"></param> 189 /// <returns></returns> 190 public AdoHelper GetHelper(DcicDbConnInfo dataConInfomation) 191 { 192 return MyDB.GetDBHelperByProviderString( 193 "PWMIS.DataProvider.Data.OracleDataAccess.Oracle,PWMIS.OracleClient", 194 $"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST={dataConInfomation.Ip})(PORT={dataConInfomation.Port}))(CONNECT_DATA=(SID={dataConInfomation.Sid})));User Id={dataConInfomation.UserId};Password={dataConInfomation.Pwd};"); 195 } 196 197 /// <summary> 198 /// 增加一条记录 199 /// </summary> 200 /// <typeparam name="T"></typeparam> 201 /// <param name="model"></param> 202 /// <param name="db"></param> 203 /// <returns></returns> 204 public bool Insert<T>(T model, AdoHelper db) where T : EntityBase, new() 205 { 206 var query = new EntityQuery<T>(db); 207 var result = query.Insert(model); 208 209 return result == 1; 210 } 211 212 /// <summary> 213 /// 执行一个无返回值的OQL语句 214 /// </summary> 215 /// <param name="oql"></param> 216 /// <param name="db"></param> 217 /// <returns></returns> 218 public bool ExecuteOql(OQL oql, AdoHelper db) 219 { 220 var result = EntityQuery.ExecuteOql(oql, db); 221 222 return result == 1; 223 } 224 225 /// <summary> 226 /// 删除一条记录,必须有主键 227 /// </summary> 228 /// <typeparam name="T"></typeparam> 229 /// <param name="model"></param> 230 /// <param name="db"></param> 231 /// <returns></returns> 232 public bool Delete<T>(T model, AdoHelper db) where T : EntityBase, new() 233 { 234 var query = new EntityQuery<T>(db); 235 var result = query.Delete(model); 236 237 return result == 1; 238 } 239 240 /// <summary> 241 /// 更新一条记录,必须有主键 242 /// </summary> 243 /// <typeparam name="T"></typeparam> 244 /// <param name="model"></param> 245 /// <param name="db"></param> 246 /// <returns></returns> 247 public bool Update<T>(T model, AdoHelper db) where T : EntityBase, new() 248 { 249 var query = new EntityQuery<T>(db); 250 var result = query.Update(model); 251 252 return result == 1; 253 } 254 255 /// <summary> 256 /// 用GOQL查询多条记录 257 /// </summary> 258 /// <typeparam name="T"></typeparam> 259 /// <param name="oql"></param> 260 /// <param name="db"></param> 261 /// <returns></returns> 262 public List<T> QueryList<T>(GOQL<T> oql, AdoHelper db) where T : EntityBase, new() 263 { 264 return oql.ToList(db); 265 } 266 267 /// <summary> 268 /// 用GOQL查询一条记录 269 /// </summary> 270 /// <typeparam name="T"></typeparam> 271 /// <param name="oql"></param> 272 /// <param name="db"></param> 273 /// <returns></returns> 274 public T QueryObject<T>(GOQL<T> oql, AdoHelper db) where T : EntityBase, new() 275 { 276 return oql.ToObject(db); 277 } 278 279 /// <summary> 280 /// 用OQL查询多条记录 281 /// </summary> 282 /// <typeparam name="T"></typeparam> 283 /// <param name="oql"></param> 284 /// <param name="db"></param> 285 /// <returns></returns> 286 public List<T> QueryList<T>(OQL oql, AdoHelper db) where T : EntityBase, new() 287 { 288 var query = new EntityQuery<T>(db); 289 return query.GetList(oql); 290 } 291 292 /// <summary> 293 /// 用OQL查询一条记录 294 /// </summary> 295 /// <typeparam name="T"></typeparam> 296 /// <param name="oql"></param> 297 /// <param name="db"></param> 298 /// <returns></returns> 299 public T QueryObject<T>(OQL oql, AdoHelper db) where T : EntityBase, new() 300 { 301 var query = new EntityQuery<T>(db); 302 return query.GetObject(oql); 303 } 304 305 /// <summary> 306 /// 用SQL查询多条记录 307 /// </summary> 308 /// <typeparam name="T"></typeparam> 309 /// <param name="sql"></param> 310 /// <param name="db"></param> 311 /// <returns></returns> 312 public List<T> QueryList<T>(string sql, AdoHelper db) where T : EntityBase, new() 313 { 314 return EntityQuery<T>.QueryList(db.ExecuteDataReader(sql)); 315 } 316 317 /// <summary> 318 /// 用SQL查询一条记录 319 /// </summary> 320 /// <typeparam name="T"></typeparam> 321 /// <param name="sql"></param> 322 /// <param name="db"></param> 323 /// <returns></returns> 324 public T QueryObject<T>(string sql, AdoHelper db) where T : EntityBase, new() 325 { 326 return EntityQuery<T>.QueryObject(db.ExecuteDataReader(sql)); 327 } 328 329 /// <summary> 330 /// 用于复杂查询的映射 331 /// </summary> 332 /// <param name="sql"></param> 333 /// <param name="db"></param> 334 /// <returns>实体数据容器</returns> 335 public DataReaderMapper QueryMapper(string sql, AdoHelper db) 336 { 337 return db.ExecuteMapper(sql); 338 } 339 340 #endregion 341 } 342 }