最近接手了一个旧的系统,各种陈旧的问题比较多,其中最棘手的就是操作数据库的部分,具体如下:
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: Codeplex: GITHUB: NUGET地址:
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 ///9 /// 数据库访问类 10 /// 11 public class DbHelper 12 { 13 #region 静态部分 14 15 private static AdoHelper _instance; 16 ///17 /// 获取或者设置默认的数据库操作对象,如果未设置将采用默认的配置进行实例化数据库操作对象。 18 /// 支持读写分离模式 19 /// 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 ///40 /// 增加一条记录 41 /// 42 ///43 /// 44 /// 45 public static bool Insert (T model) where T : EntityBase, new() 46 { 47 var query = new EntityQuery (Instance); 48 var result = query.Insert(model); 49 50 return result == 1; 51 } 52 53 /// 54 /// 执行一个无返回值的OQL语句 55 /// 56 /// 57 ///58 public static bool ExecuteOql(OQL oql) 59 { 60 var result = EntityQuery.ExecuteOql(oql, Instance); 61 return result == 1; 62 } 63 64 /// 65 /// 删除一条记录,必须有主键 66 /// 67 ///68 /// 69 public static bool Delete (T model) where T : EntityBase, new() 70 { 71 var query = new EntityQuery (Instance); 72 var result = query.Delete(model); 73 74 return result == 1; 75 } 76 77 /// 78 /// 更新一条记录,必须有主键 79 /// 80 ///81 /// 82 public static bool Update (T model) where T : EntityBase, new() 83 { 84 var query = new EntityQuery (Instance); 85 var result = query.Update(model); 86 87 return result == 1; 88 } 89 90 /// 91 /// 使用OQL查询多条记录 92 /// 93 ///94 /// 95 /// 96 public static List QueryList (OQL oql) where T : EntityBase, new() 97 { 98 var query = new EntityQuery (Instance); 99 return query.GetList(oql);100 }101 102 /// 103 /// 使用GOQL查询多条记录104 /// 105 ///106 /// 107 /// 108 public static List QueryList (GOQL oql) where T : EntityBase, new()109 {110 return oql.ToList(Instance);111 }112 113 /// 114 /// 使用OQL查询一条记录115 /// 116 ///117 /// 118 /// 119 public static T QueryObject (OQL oql) where T : EntityBase, new()120 {121 var query = new EntityQuery (Instance);122 123 return query.GetObject(oql);124 }125 126 /// 127 /// 使用GOQL查询一条记录128 /// 129 ///130 /// 131 /// 132 public static T QueryObject (GOQL oql) where T : EntityBase, new()133 {134 return oql.ToObject(Instance);135 }136 137 /// 138 /// 使用SQL查询多条记录139 /// 140 ///141 /// 142 /// 143 public static List QueryList (string sql) where T : EntityBase, new()144 {145 return EntityQuery .QueryList(Instance.ExecuteDataReader(sql));146 }147 148 /// 149 /// 使用SQL查询一条记录150 /// 151 ///152 /// 153 /// 154 public static T QueryObject (string sql) where T : EntityBase, new()155 {156 return EntityQuery .QueryObject(Instance.ExecuteDataReader(sql));157 }158 159 /// 160 /// 用于复杂查询的映射161 /// 162 /// 163 ///实体数据容器 164 public static DataReaderMapper QueryMapper(string sql)165 {166 return Instance.ExecuteMapper(sql);167 }168 169 #endregion170 171 #region 动态部分172 173 ///174 /// 获取各种数据库的DbHelper175 /// 176 /// 177 /// 178 ///179 public AdoHelper GetHelper(string providerName, string connectionString)180 {181 return MyDB.GetDBHelperByProviderString(providerName,182 connectionString);183 }184 185 /// 186 /// 获取Oracle数据库的DbHelper187 /// 188 /// 189 ///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 /// 198 /// 增加一条记录199 /// 200 ///201 /// 202 /// 203 /// 204 public bool Insert (T model, AdoHelper db) where T : EntityBase, new()205 {206 var query = new EntityQuery (db);207 var result = query.Insert(model);208 209 return result == 1;210 }211 212 /// 213 /// 执行一个无返回值的OQL语句214 /// 215 /// 216 /// 217 ///218 public bool ExecuteOql(OQL oql, AdoHelper db)219 {220 var result = EntityQuery.ExecuteOql(oql, db);221 222 return result == 1;223 }224 225 /// 226 /// 删除一条记录,必须有主键227 /// 228 ///229 /// 230 /// 231 /// 232 public bool Delete (T model, AdoHelper db) where T : EntityBase, new()233 {234 var query = new EntityQuery (db);235 var result = query.Delete(model);236 237 return result == 1;238 }239 240 /// 241 /// 更新一条记录,必须有主键242 /// 243 ///244 /// 245 /// 246 /// 247 public bool Update (T model, AdoHelper db) where T : EntityBase, new()248 {249 var query = new EntityQuery (db);250 var result = query.Update(model);251 252 return result == 1;253 }254 255 /// 256 /// 用GOQL查询多条记录257 /// 258 ///259 /// 260 /// 261 /// 262 public List QueryList (GOQL oql, AdoHelper db) where T : EntityBase, new()263 {264 return oql.ToList(db);265 }266 267 /// 268 /// 用GOQL查询一条记录269 /// 270 ///271 /// 272 /// 273 /// 274 public T QueryObject (GOQL oql, AdoHelper db) where T : EntityBase, new()275 {276 return oql.ToObject(db);277 }278 279 /// 280 /// 用OQL查询多条记录281 /// 282 ///283 /// 284 /// 285 /// 286 public List QueryList (OQL oql, AdoHelper db) where T : EntityBase, new()287 {288 var query = new EntityQuery (db);289 return query.GetList(oql);290 }291 292 /// 293 /// 用OQL查询一条记录294 /// 295 ///296 /// 297 /// 298 /// 299 public T QueryObject (OQL oql, AdoHelper db) where T : EntityBase, new()300 {301 var query = new EntityQuery (db);302 return query.GetObject(oql);303 }304 305 /// 306 /// 用SQL查询多条记录307 /// 308 ///309 /// 310 /// 311 /// 312 public List QueryList (string sql, AdoHelper db) where T : EntityBase, new()313 {314 return EntityQuery .QueryList(db.ExecuteDataReader(sql));315 }316 317 /// 318 /// 用SQL查询一条记录319 /// 320 ///321 /// 322 /// 323 /// 324 public T QueryObject (string sql, AdoHelper db) where T : EntityBase, new()325 {326 return EntityQuery .QueryObject(db.ExecuteDataReader(sql));327 }328 329 /// 330 /// 用于复杂查询的映射331 /// 332 /// 333 /// 334 ///实体数据容器 335 public DataReaderMapper QueryMapper(string sql, AdoHelper db)336 {337 return db.ExecuteMapper(sql);338 }339 340 #endregion341 }342 }