BaseDALAccess.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. using System;
  2. using System.Text;
  3. using System.Collections;
  4. using System.Data;
  5. using System.Data.OleDb;
  6. using System.Data.Common;
  7. using System.Collections.Generic;
  8. using System.Reflection;
  9. using System.Configuration;
  10. using Microsoft.Practices.EnterpriseLibrary.Data;
  11. using Microsoft.Practices.EnterpriseLibrary.Data.Configuration;
  12. using ProjectBase.Data.Logs;
  13. using ProjectBase.Data.Pager;
  14. using System.Data.SqlClient;
  15. using ProjectBase.Data.BaseDAL;
  16. using ProjectBase.Data.Encrypt;
  17. namespace WHC.Framework.ControlUtil
  18. {
  19. /// <summary>
  20. /// 数据访问层的基类
  21. /// </summary>
  22. public abstract class BaseDALAccess<T> : AbstractBaseDAL<T>, IBaseDAL<T> where T : BaseEntity, new()
  23. {
  24. #region 构造函数
  25. /// <summary>
  26. /// 默认构造函数
  27. /// </summary>
  28. public BaseDALAccess() { }
  29. /// <summary>
  30. /// 指定表名以及主键,对基类进构造
  31. /// </summary>
  32. /// <param name="tableName">表名</param>
  33. /// <param name="primaryKey">表主键</param>
  34. public BaseDALAccess(string tableName, string primaryKey)
  35. : base(tableName, primaryKey)
  36. {
  37. parameterPrefix = "@"; //数据库参数化访问的占位符
  38. safeFieldFormat = "[{0}]"; //防止和保留字、关键字同名的字段格式,如[value]
  39. }
  40. #endregion
  41. #region 通用操作方法
  42. /// <summary>
  43. /// 添加记录
  44. /// </summary>
  45. /// <param name="recordField">Hashtable:键[key]为字段名;值[value]为字段对应的值</param>
  46. /// <param name="targetTable">需要操作的目标表名称</param>
  47. /// <param name="trans">事务对象,如果使用事务,传入事务对象,否则为Null不使用事务</param>
  48. public override bool Insert(Hashtable recordField, string targetTable, DbTransaction trans)
  49. {
  50. bool result = false;
  51. string fields = ""; // 字段名
  52. string vals = ""; // 字段值
  53. if (recordField == null || recordField.Count < 1)
  54. {
  55. return result;
  56. }
  57. OleDbParameter[] param = new OleDbParameter[recordField.Count];
  58. IEnumerator eKeys = recordField.Keys.GetEnumerator();
  59. int i = 0;
  60. while (eKeys.MoveNext())
  61. {
  62. string field = eKeys.Current.ToString();
  63. fields += string.Format("[{0}],", field);//加[]为了去除别名引起的错误
  64. vals += string.Format("@{0},", field);
  65. object val = recordField[eKeys.Current.ToString()];
  66. val = val ?? DBNull.Value;
  67. if (val is DateTime)
  68. {
  69. if (Convert.ToDateTime(val) <= Convert.ToDateTime("1753-1-1"))
  70. {
  71. val = DBNull.Value;
  72. }
  73. }
  74. param[i] = new OleDbParameter("@" + field, val);
  75. if (val is DateTime)
  76. {
  77. param[i].OleDbType = OleDbType.Date;//日期类型特别处理,否则Access数据库访问出错
  78. }
  79. i++;
  80. }
  81. fields = fields.Trim(',');//除去前后的逗号
  82. vals = vals.Trim(',');//除去前后的逗号
  83. string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", targetTable, fields, vals);
  84. Database db = CreateDatabase();
  85. DbCommand command = db.GetSqlStringCommand(sql);
  86. command.Parameters.AddRange(param);
  87. if (trans != null)
  88. {
  89. result = db.ExecuteNonQuery(command, trans) > 0;
  90. }
  91. else
  92. {
  93. result = db.ExecuteNonQuery(command) > 0;
  94. }
  95. return result;
  96. }
  97. /// <summary>
  98. /// 添加记录
  99. /// </summary>
  100. /// <param name="recordField">Hashtable:键[key]为字段名;值[value]为字段对应的值</param>
  101. /// <param name="targetTable">需要操作的目标表名称</param>
  102. /// <param name="trans">事务对象,如果使用事务,传入事务对象,否则为Null不使用事务</param>
  103. public override int Insert2(Hashtable recordField, string targetTable, DbTransaction trans)
  104. {
  105. int result = -1;
  106. string fields = ""; // 字段名
  107. string vals = ""; // 字段值
  108. if (recordField == null || recordField.Count < 1)
  109. {
  110. return result;
  111. }
  112. OleDbParameter[] param = new OleDbParameter[recordField.Count];
  113. IEnumerator eKeys = recordField.Keys.GetEnumerator();
  114. int i = 0;
  115. while (eKeys.MoveNext())
  116. {
  117. string field = eKeys.Current.ToString();
  118. fields += string.Format("[{0}],", field);//加[]为了去除别名引起的错误
  119. vals += string.Format("@{0},", field);
  120. object val = recordField[eKeys.Current.ToString()];
  121. val = val ?? DBNull.Value;
  122. if (val is DateTime)
  123. {
  124. if (Convert.ToDateTime(val) <= Convert.ToDateTime("1753-1-1"))
  125. {
  126. val = DBNull.Value;
  127. }
  128. }
  129. param[i] = new OleDbParameter("@" + field, val);
  130. if (val is DateTime)
  131. {
  132. param[i].OleDbType = OleDbType.Date;//日期类型特别处理,否则Access数据库访问出错
  133. }
  134. i++;
  135. }
  136. fields = fields.Trim(',');//除去前后的逗号
  137. vals = vals.Trim(',');//除去前后的逗号
  138. string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2});SELECT @@IDENTITY", targetTable, fields, vals);//SCOPE_IDENTITY()
  139. Database db = CreateDatabase();
  140. DbCommand command = db.GetSqlStringCommand(sql);
  141. command.Parameters.AddRange(param);
  142. if (trans != null)
  143. {
  144. result = Convert.ToInt32(db.ExecuteScalar(command, trans).ToString());
  145. }
  146. else
  147. {
  148. result = Convert.ToInt32(db.ExecuteScalar(command).ToString());
  149. }
  150. return result;
  151. }
  152. /// <summary>
  153. /// 更新某个表一条记录
  154. /// </summary>
  155. /// <param name="id">ID值</param>
  156. /// <param name="recordField">Hashtable:键[key]为字段名;值[value]为字段对应的值</param>
  157. /// <param name="targetTable">需要操作的目标表名称</param>
  158. /// <param name="trans">事务对象,如果使用事务,传入事务对象,否则为Null不使用事务</param>
  159. public override bool PrivateUpdate(object id, Hashtable recordField, string targetTable, DbTransaction trans)
  160. {
  161. try
  162. {
  163. if (recordField == null || recordField.Count < 1)
  164. {
  165. return false;
  166. }
  167. string setValue = "";
  168. foreach (string field in recordField.Keys)
  169. {
  170. setValue += string.Format("{0} = {1}{2},", GetSafeFileName(field), parameterPrefix, field);
  171. }
  172. string sql = string.Format("UPDATE {0} SET {1} WHERE {2} = {3}{2} ",
  173. targetTable, setValue.Substring(0, setValue.Length - 1), primaryKey, parameterPrefix);
  174. Database db = CreateDatabase();
  175. DbCommand command = db.GetSqlStringCommand(sql);
  176. bool foundID = false;
  177. foreach (string field in recordField.Keys)
  178. {
  179. object val = recordField[field];
  180. val = val ?? DBNull.Value;
  181. if (val is DateTime)
  182. {
  183. if (Convert.ToDateTime(val) <= Convert.ToDateTime("1753-1-1"))
  184. {
  185. val = DBNull.Value;
  186. }
  187. db.AddInParameter(command, field, DbType.Date, val);//Access日期必须使用DbType.Date,如果使用 DbType.DateTime会出现类型不匹配错误
  188. }
  189. else
  190. {
  191. db.AddInParameter(command, field, TypeToDbType(val.GetType()), val);
  192. }
  193. if (field.Equals(primaryKey, StringComparison.OrdinalIgnoreCase))
  194. {
  195. foundID = true;
  196. }
  197. }
  198. if (!foundID)
  199. {
  200. db.AddInParameter(command, primaryKey, TypeToDbType(id.GetType()), id);
  201. }
  202. bool result = false;
  203. if (trans != null)
  204. {
  205. result = db.ExecuteNonQuery(command, trans) > 0;
  206. }
  207. else
  208. {
  209. result = db.ExecuteNonQuery(command) > 0;
  210. }
  211. return result;
  212. }
  213. catch (Exception ex)
  214. {
  215. LogHelper.log.Error(ex.ToString());
  216. throw;
  217. }
  218. }
  219. /// <summary>
  220. /// 更新某个表一条记录
  221. /// </summary>
  222. /// <param name="id">ID值</param>
  223. /// <param name="recordField">Hashtable:键[key]为字段名;值[value]为字段对应的值</param>
  224. /// <param name="targetTable">需要操作的目标表名称</param>
  225. /// <param name="trans">事务对象,如果使用事务,传入事务对象,否则为Null不使用事务</param>
  226. public bool PrivateUpdate2(object id, Hashtable recordField, string targetTable, DbTransaction trans)
  227. {
  228. string field = ""; // 字段名
  229. object val = null; // 值
  230. string setValue = ""; // 更新Set () 中的语句
  231. if (recordField == null || recordField.Count < 1)
  232. {
  233. return false;
  234. }
  235. OleDbParameter[] param = new OleDbParameter[recordField.Count];
  236. int i = 0;
  237. IEnumerator eKeys = recordField.Keys.GetEnumerator();
  238. while (eKeys.MoveNext())
  239. {
  240. field = eKeys.Current.ToString();
  241. val = recordField[eKeys.Current.ToString()];
  242. val = val ?? DBNull.Value;
  243. if (val is DateTime)
  244. {
  245. if (Convert.ToDateTime(val) <= Convert.ToDateTime("1753-1-1"))
  246. {
  247. val = DBNull.Value;
  248. }
  249. }
  250. setValue += string.Format("[{0}] = @{0},", field);//加[ ]用来避免关键字错误
  251. param[i] = new OleDbParameter(string.Format("@{0}", field), val);
  252. if (val is DateTime)
  253. {
  254. param[i].OleDbType = OleDbType.Date;//日期类型特别处理,否则Access数据库访问出错
  255. }
  256. i++;
  257. }
  258. string sql = "";
  259. //为了避免整形ID在更新语句Where ID ='1'出现“标准表达式中数据类型不匹配”错误
  260. ////因此设置不同类型,更新语句不同的条件语句。
  261. //if (id.GetType() == typeof(int) || ValidateUtil.IsNumber(id.ToString()))
  262. //{
  263. // sql = string.Format("UPDATE {0} SET {1} WHERE {2} = {3} ", targetTable, setValue.Substring(0, setValue.Length - 1), primaryKey, id);
  264. //}
  265. //else
  266. // sql = string.Format("UPDATE {0} SET {1} WHERE {2} = '{3}' ", targetTable, setValue.Substring(0, setValue.Length - 1), primaryKey, id);
  267. //{
  268. //}
  269. LogHelper.log.Debug(sql);
  270. Database db = CreateDatabase();
  271. DbCommand command = db.GetSqlStringCommand(sql);
  272. command.Parameters.AddRange(param);
  273. bool result = false;
  274. if (trans != null)
  275. {
  276. result = db.ExecuteNonQuery(command, trans) > 0;
  277. }
  278. else
  279. {
  280. result = db.ExecuteNonQuery(command) > 0;
  281. }
  282. return result;
  283. }
  284. /// <summary>
  285. /// 测试数据库是否正常连接
  286. /// </summary>
  287. public override bool TestConnection(string connectionString)
  288. {
  289. bool result = false;
  290. using (DbConnection connection = new OleDbConnection(connectionString))
  291. {
  292. connection.Open();
  293. if (connection.State == System.Data.ConnectionState.Open)
  294. {
  295. result = true;
  296. }
  297. }
  298. return result;
  299. }
  300. #endregion
  301. #region 对象添加、修改、查询接口
  302. /// <summary>
  303. /// 查找记录表中最旧的一条记录
  304. /// </summary>
  305. /// <param name="trans">事务对象</param>
  306. /// <returns></returns>
  307. public override T FindFirst(DbTransaction trans = null)
  308. {
  309. string sql = string.Format("Select top 1 {0} From {1} Order by {2} ASC", selectedFields, tableName, GetSafeFileName(sortField));
  310. Database db = CreateDatabase();
  311. DbCommand command = db.GetSqlStringCommand(sql);
  312. T entity = GetEntity(db, command, trans);
  313. return entity;
  314. }
  315. /// <summary>
  316. /// 查找记录表中最新的一条记录
  317. /// </summary>
  318. /// <param name="trans">事务对象</param>
  319. /// <returns></returns>
  320. public override T FindLast(DbTransaction trans = null)
  321. {
  322. string sql = string.Format("Select top 1 {0} From {1} Order by {2} DESC", selectedFields, tableName, GetSafeFileName(sortField));
  323. Database db = CreateDatabase();
  324. DbCommand command = db.GetSqlStringCommand(sql);
  325. T entity = GetEntity(db, command, trans);
  326. return entity;
  327. }
  328. #region 下面两个覆盖基类函数,指定具体的数据库类型
  329. /// <summary>
  330. /// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
  331. /// </summary>
  332. /// <param name="condition">查询的条件</param>
  333. /// <param name="info">分页实体</param>
  334. /// <param name="fieldToSort">排序字段</param>
  335. /// <param name="desc">是否降序</param>
  336. /// <param name="trans">事务对象</param>
  337. /// <returns>指定对象的集合</returns>
  338. public override List<T> FindWithPager(string condition, PagerInfo info, string fieldToSort, bool desc, DbTransaction trans = null)
  339. {
  340. if (HasInjectionData(condition))
  341. {
  342. LogHelper.log.Error(string.Format("检测出SQL注入的恶意数据, {0}", condition));
  343. throw new Exception("检测出SQL注入的恶意数据");
  344. }
  345. PagerHelper helper = new PagerHelper(tableName, this.selectedFields, fieldToSort,
  346. info.PageSize, info.CurrenetPageIndex, desc, condition);
  347. string countSql = helper.GetPagingSql(DatabaseType.Access, true);
  348. string strCount = SqlValueList(countSql, trans);
  349. info.RecordCount = Convert.ToInt32(strCount);
  350. string dataSql = helper.GetPagingSql(DatabaseType.Access, false);
  351. List<T> list = GetList(dataSql, null, trans);
  352. return list;
  353. }
  354. /// <summary>
  355. /// 根据条件查询数据库,并返回DataTable集合(用于分页数据显示)
  356. /// </summary>
  357. /// <param name="condition">查询的条件</param>
  358. /// <param name="info">分页实体</param>
  359. /// <param name="fieldToSort">排序字段</param>
  360. /// <param name="desc">是否降序</param>
  361. /// <param name="trans">事务对象</param>
  362. /// <returns>指定DataTable的集合</returns>
  363. public override DataTable FindToDataTable(string condition, PagerInfo info, string fieldToSort, bool desc, DbTransaction trans = null)
  364. {
  365. if (HasInjectionData(condition))
  366. {
  367. LogHelper.log.Error(string.Format("检测出SQL注入的恶意数据, {0}", condition));
  368. throw new Exception("检测出SQL注入的恶意数据");
  369. }
  370. PagerHelper helper = new PagerHelper(tableName, this.selectedFields, fieldToSort,
  371. info.PageSize, info.CurrenetPageIndex, desc, condition);
  372. string countSql = helper.GetPagingSql(DatabaseType.Access, true);
  373. string strCount = SqlValueList(countSql, trans);
  374. info.RecordCount = Convert.ToInt32(strCount);
  375. string dataSql = helper.GetPagingSql(DatabaseType.Access, false);
  376. return GetDataTableBySql(dataSql, trans);
  377. }
  378. #endregion
  379. /// <summary>
  380. /// 获取前面记录指定数量的记录
  381. /// </summary>
  382. /// <param name="sql">查询语句</param>
  383. /// <param name="count">指定数量</param>
  384. /// <param name="orderBy">排序条件,例如order by id</param>
  385. /// <param name="trans">事务对象</param>
  386. /// <returns></returns>
  387. public override DataTable GetTopResult(string sql, int count, string orderBy, DbTransaction trans = null)
  388. {
  389. string resultSql = string.Format("select top {0} * from ({1} {2}) ", count, sql, orderBy);
  390. return SqlTable(resultSql, trans);
  391. }
  392. #endregion
  393. #region 特殊的操作
  394. /// <summary>
  395. /// 兼容Oracle的字段大写的重写函数
  396. /// </summary>
  397. /// <param name="sql">sql语句</param>
  398. /// <param name="trans">事务对象</param>
  399. /// <returns></returns>
  400. public override DataTable SqlTable(string sql, DbTransaction trans = null)
  401. {
  402. //由于Sqlite字段查询不区分大小写,因此要返回大写字段,不能通过改变Sql大写方式
  403. //通过代码改变列的名称为大写即可
  404. DataTable dt = base.SqlTable(sql, trans);
  405. foreach (DataColumn col in dt.Columns)
  406. {
  407. col.ColumnName = col.ColumnName.ToUpper();
  408. }
  409. return dt;
  410. }
  411. /// <summary>
  412. /// 兼容Oracle的字段大写的重写函数
  413. /// </summary>
  414. /// <param name="sql">sql语句</param>
  415. /// <param name="parameters">SQL参数集合</param>
  416. /// <param name="trans">事务对象</param>
  417. /// <returns></returns>
  418. public override DataTable SqlTable(string sql, DbParameter[] parameters, DbTransaction trans = null)
  419. {
  420. //由于Sqlite字段查询不区分大小写,因此要返回大写字段,不能通过改变Sql大写方式
  421. //通过代码改变列的名称为大写即可
  422. DataTable dt = base.SqlTable(sql, parameters, trans);
  423. foreach (DataColumn col in dt.Columns)
  424. {
  425. col.ColumnName = col.ColumnName.ToUpper();
  426. }
  427. return dt;
  428. }
  429. /// <summary>
  430. /// 获取数据库的全部表名称
  431. /// </summary>
  432. /// <returns></returns>
  433. public override List<string> GetTableNames()
  434. {
  435. Database db = CreateDatabase();
  436. List<string> list = new List<string>();
  437. using (DbConnection connection = db.CreateConnection())
  438. {
  439. if (connection.State != ConnectionState.Open)
  440. {
  441. connection.Open();
  442. }
  443. DataTable schemaTable = connection.GetSchema("TABLES");
  444. for (int i = 0; i < schemaTable.Rows.Count; i++)
  445. {
  446. string tablename = schemaTable.Rows[i]["TABLE_NAME"].ToString();
  447. list.Add(tablename);
  448. }
  449. }
  450. return list;
  451. }
  452. #endregion
  453. #region 设置数据库的密码
  454. /// <summary>
  455. /// 根据配置数据库配置名称生成Database对象
  456. /// </summary>
  457. /// <returns></returns>
  458. protected override Database CreateDatabase()
  459. {
  460. Database db = null;
  461. if (string.IsNullOrEmpty(dbConfigName))
  462. {
  463. db = DatabaseFactory.CreateDatabase();
  464. }
  465. else
  466. {
  467. db = DatabaseFactory.CreateDatabase(dbConfigName);
  468. }
  469. DbConnectionStringBuilder sb = db.DbProviderFactory.CreateConnectionStringBuilder();
  470. sb.ConnectionString = GetConnectionString(dbConfigName);
  471. GenericDatabase newDb = new GenericDatabase(sb.ToString(), db.DbProviderFactory);
  472. db = newDb;
  473. return db;
  474. }
  475. /// <summary>
  476. /// 动态改变或者连接字符串
  477. /// </summary>
  478. /// <returns></returns>
  479. protected virtual string GetConnectionString(string dbConfigName)
  480. {
  481. string connectionString = "";
  482. DatabaseSettings setting = ConfigurationManager.GetSection("dataConfiguration") as DatabaseSettings;
  483. if (setting != null)
  484. {
  485. string connection = string.IsNullOrEmpty(dbConfigName) ? setting.DefaultDatabase : dbConfigName;
  486. connectionString = ConfigurationManager.ConnectionStrings[connection].ConnectionString;
  487. #region 加密解密操作
  488. //使用自定义加密
  489. //if (!connectionString.EndsWith(";"))
  490. //{
  491. // connectionString += ";";
  492. //}
  493. //connectionString += string.Format("Jet OLEDB:Database Password=wuhuacong2013;");
  494. string passwordKey = "Jet OLEDB:Database Password";
  495. string password = GetSubValue(connectionString, passwordKey);
  496. if (!string.IsNullOrEmpty(password))
  497. {
  498. //尝试使用AES解密
  499. string decryptStr = password;
  500. try
  501. {
  502. decryptStr = EncodeHelper.AES_Decrypt(password);
  503. }
  504. catch
  505. {
  506. decryptStr = password;
  507. //throw new InvalidOperationException("无法解密数据库");
  508. }
  509. connectionString += string.Format(";{0}={1};", passwordKey, decryptStr);
  510. }
  511. #endregion
  512. }
  513. return connectionString;
  514. }
  515. #endregion
  516. }
  517. }