最近接手了一箇舊的系統,各種陳舊的問題比較多,其中最棘手的就是運算元據庫的部分,具體如下:
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 }