MySqlDatabase.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. using System.Threading.Tasks;
  9. using System.Data;
  10. using System.Data.Common;
  11. using Microsoft.EntityFrameworkCore.Storage;
  12. using Microsoft.EntityFrameworkCore;
  13. using Microsoft.EntityFrameworkCore.Metadata;
  14. using YiSha.Util.Extension;
  15. namespace YiSha.Data.EF
  16. {
  17. public class MySqlDatabase : IDatabase
  18. {
  19. #region 构造函数
  20. /// <summary>
  21. /// 构造方法
  22. /// </summary>
  23. public MySqlDatabase(string connString)
  24. {
  25. dbContext = new MySqlDbContext(connString);
  26. }
  27. #endregion
  28. #region 属性
  29. /// <summary>
  30. /// 获取 当前使用的数据访问上下文对象
  31. /// </summary>
  32. public DbContext dbContext { get; set; }
  33. /// <summary>
  34. /// 事务对象
  35. /// </summary>
  36. public IDbContextTransaction dbContextTransaction { get; set; }
  37. #endregion
  38. #region 事务提交
  39. /// <summary>
  40. /// 事务开始
  41. /// </summary>
  42. /// <returns></returns>
  43. public async Task<IDatabase> BeginTrans()
  44. {
  45. DbConnection dbConnection = dbContext.Database.GetDbConnection();
  46. if (dbConnection.State == ConnectionState.Closed)
  47. {
  48. await dbConnection.OpenAsync();
  49. }
  50. dbContextTransaction = await dbContext.Database.BeginTransactionAsync();
  51. return this;
  52. }
  53. /// <summary>
  54. /// 提交当前操作的结果
  55. /// </summary>
  56. public async Task<int> CommitTrans()
  57. {
  58. try
  59. {
  60. DbContextExtension.SetEntityDefaultValue(dbContext);
  61. int returnValue = await dbContext.SaveChangesAsync();
  62. if (dbContextTransaction != null)
  63. {
  64. await dbContextTransaction.CommitAsync();
  65. await this.Close();
  66. }
  67. else
  68. {
  69. await this.Close();
  70. }
  71. return returnValue;
  72. }
  73. catch
  74. {
  75. throw;
  76. }
  77. finally
  78. {
  79. if (dbContextTransaction == null)
  80. {
  81. await this.Close();
  82. }
  83. }
  84. }
  85. /// <summary>
  86. /// 把当前操作回滚成未提交状态
  87. /// </summary>
  88. public async Task RollbackTrans()
  89. {
  90. await this.dbContextTransaction.RollbackAsync();
  91. await this.dbContextTransaction.DisposeAsync();
  92. await this.Close();
  93. }
  94. /// <summary>
  95. /// 关闭连接 内存回收
  96. /// </summary>
  97. public async Task Close()
  98. {
  99. await dbContext.DisposeAsync();
  100. }
  101. #endregion
  102. #region 执行 SQL 语句
  103. public async Task<int> ExecuteBySql(string strSql)
  104. {
  105. if (dbContextTransaction == null)
  106. {
  107. return await dbContext.Database.ExecuteSqlRawAsync(strSql);
  108. }
  109. else
  110. {
  111. await dbContext.Database.ExecuteSqlRawAsync(strSql);
  112. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  113. }
  114. }
  115. public async Task<int> ExecuteBySql(string strSql, params DbParameter[] dbParameter)
  116. {
  117. if (dbContextTransaction == null)
  118. {
  119. return await dbContext.Database.ExecuteSqlRawAsync(strSql, dbParameter);
  120. }
  121. else
  122. {
  123. await dbContext.Database.ExecuteSqlRawAsync(strSql, dbParameter);
  124. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  125. }
  126. }
  127. public async Task<int> ExecuteByProc(string procName)
  128. {
  129. if (dbContextTransaction == null)
  130. {
  131. return await dbContext.Database.ExecuteSqlRawAsync(DbContextExtension.BuilderProc(procName));
  132. }
  133. else
  134. {
  135. await dbContext.Database.ExecuteSqlRawAsync(DbContextExtension.BuilderProc(procName));
  136. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  137. }
  138. }
  139. public async Task<int> ExecuteByProc(string procName, params DbParameter[] dbParameter)
  140. {
  141. if (dbContextTransaction == null)
  142. {
  143. return await dbContext.Database.ExecuteSqlRawAsync(DbContextExtension.BuilderProc(procName, dbParameter), dbParameter);
  144. }
  145. else
  146. {
  147. await dbContext.Database.ExecuteSqlRawAsync(DbContextExtension.BuilderProc(procName, dbParameter), dbParameter);
  148. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  149. }
  150. }
  151. #endregion
  152. #region 对象实体 添加、修改、删除
  153. public async Task<int> Insert<T>(T entity) where T : class
  154. {
  155. dbContext.Entry<T>(entity).State = EntityState.Added;
  156. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  157. }
  158. public async Task<int> Insert<T>(IEnumerable<T> entities) where T : class
  159. {
  160. foreach (var entity in entities)
  161. {
  162. dbContext.Entry<T>(entity).State = EntityState.Added;
  163. }
  164. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  165. }
  166. public async Task<int> Delete<T>() where T : class
  167. {
  168. IEntityType entityType = DbContextExtension.GetEntityType<T>(dbContext);
  169. if (entityType != null)
  170. {
  171. string tableName = entityType.GetTableName();
  172. return await this.ExecuteBySql(DbContextExtension.DeleteSql(tableName));
  173. }
  174. return -1;
  175. }
  176. public async Task<int> Delete<T>(T entity) where T : class
  177. {
  178. dbContext.Set<T>().Attach(entity);
  179. dbContext.Set<T>().Remove(entity);
  180. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  181. }
  182. public async Task<int> Delete<T>(IEnumerable<T> entities) where T : class
  183. {
  184. foreach (var entity in entities)
  185. {
  186. dbContext.Set<T>().Attach(entity);
  187. dbContext.Set<T>().Remove(entity);
  188. }
  189. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  190. }
  191. public async Task<int> Delete<T>(Expression<Func<T, bool>> condition) where T : class, new()
  192. {
  193. IEnumerable<T> entities = await dbContext.Set<T>().Where(condition).ToListAsync();
  194. return entities.Count() > 0 ? await Delete(entities) : 0;
  195. }
  196. public async Task<int> Delete<T>(string keyValue) where T : class
  197. {
  198. IEntityType entityType = DbContextExtension.GetEntityType<T>(dbContext);
  199. if (entityType != null)
  200. {
  201. string tableName = entityType.GetTableName();
  202. string keyField = "Id";
  203. return await this.ExecuteBySql(DbContextExtension.DeleteSql(tableName, keyField, keyValue));
  204. }
  205. return -1;
  206. }
  207. public async Task<int> Delete<T>(string[] keyValue) where T : class
  208. {
  209. IEntityType entityType = DbContextExtension.GetEntityType<T>(dbContext);
  210. if (entityType != null)
  211. {
  212. string tableName = entityType.GetTableName();
  213. string keyField = "Id";
  214. return await this.ExecuteBySql(DbContextExtension.DeleteSql(tableName, keyField, keyValue));
  215. }
  216. return -1;
  217. }
  218. public async Task<int> Delete<T>(string propertyName, string propertyValue) where T : class
  219. {
  220. IEntityType entityType = DbContextExtension.GetEntityType<T>(dbContext);
  221. if (entityType != null)
  222. {
  223. string tableName = entityType.GetTableName();
  224. return await this.ExecuteBySql(DbContextExtension.DeleteSql(tableName, propertyName, propertyValue));
  225. }
  226. return -1;
  227. }
  228. public async Task<int> Update<T>(T entity) where T : class
  229. {
  230. dbContext.Set<T>().Attach(entity);
  231. Hashtable props = DatabasesExtension.GetPropertyInfo<T>(entity);
  232. foreach (string item in props.Keys)
  233. {
  234. if (item == "Id")
  235. {
  236. continue;
  237. }
  238. object value = dbContext.Entry(entity).Property(item).CurrentValue;
  239. if (value != null)
  240. {
  241. dbContext.Entry(entity).Property(item).IsModified = true;
  242. }
  243. }
  244. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  245. }
  246. public async Task<int> Update<T>(IEnumerable<T> entities) where T : class
  247. {
  248. foreach (var entity in entities)
  249. {
  250. dbContext.Entry<T>(entity).State = EntityState.Modified;
  251. }
  252. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  253. }
  254. public async Task<int> UpdateAllField<T>(T entity) where T : class
  255. {
  256. dbContext.Set<T>().Attach(entity);
  257. dbContext.Entry(entity).State = EntityState.Modified;
  258. return dbContextTransaction == null ? await this.CommitTrans() : 0;
  259. }
  260. public async Task<int> Update<T>(Expression<Func<T, bool>> condition) where T : class, new()
  261. {
  262. IEnumerable<T> entities = await dbContext.Set<T>().Where(condition).ToListAsync();
  263. return entities.Count() > 0 ? await Update(entities) : 0;
  264. }
  265. public IQueryable<T> IQueryable<T>(Expression<Func<T, bool>> condition) where T : class, new()
  266. {
  267. return dbContext.Set<T>().Where(condition);
  268. }
  269. #endregion
  270. #region 对象实体 查询
  271. public async Task<T> FindEntity<T>(object keyValue) where T : class
  272. {
  273. return await dbContext.Set<T>().FindAsync(keyValue);
  274. }
  275. public async Task<T> FindEntity<T>(Expression<Func<T, bool>> condition) where T : class, new()
  276. {
  277. return await dbContext.Set<T>().Where(condition).FirstOrDefaultAsync();
  278. }
  279. public async Task<IEnumerable<T>> FindList<T>() where T : class, new()
  280. {
  281. return await dbContext.Set<T>().ToListAsync();
  282. }
  283. public async Task<IEnumerable<T>> FindList<T>(Func<T, object> orderby) where T : class, new()
  284. {
  285. var list = await dbContext.Set<T>().ToListAsync();
  286. list = list.OrderBy(orderby).ToList();
  287. return list;
  288. }
  289. public async Task<IEnumerable<T>> FindList<T>(Expression<Func<T, bool>> condition) where T : class, new()
  290. {
  291. return await dbContext.Set<T>().Where(condition).ToListAsync();
  292. }
  293. public async Task<IEnumerable<T>> FindList<T>(string strSql) where T : class
  294. {
  295. return await FindList<T>(strSql, null);
  296. }
  297. public async Task<IEnumerable<T>> FindList<T>(string strSql, DbParameter[] dbParameter) where T : class
  298. {
  299. using (var dbConnection = dbContext.Database.GetDbConnection())
  300. {
  301. var reader = await new DbHelper(dbContext, dbConnection).ExecuteReadeAsync(CommandType.Text, strSql, dbParameter);
  302. return DatabasesExtension.IDataReaderToList<T>(reader);
  303. }
  304. }
  305. public async Task<(int total, IEnumerable<T> list)> FindList<T>(string sort, bool isAsc, int pageSize, int pageIndex) where T : class, new()
  306. {
  307. var tempData = dbContext.Set<T>().AsQueryable();
  308. return await FindList<T>(tempData, sort, isAsc, pageSize, pageIndex);
  309. }
  310. public async Task<(int total, IEnumerable<T> list)> FindList<T>(Expression<Func<T, bool>> condition, string sort, bool isAsc, int pageSize, int pageIndex) where T : class, new()
  311. {
  312. var tempData = dbContext.Set<T>().Where(condition);
  313. return await FindList<T>(tempData, sort, isAsc, pageSize, pageIndex);
  314. }
  315. public async Task<(int total, IEnumerable<T>)> FindList<T>(string strSql, string sort, bool isAsc, int pageSize, int pageIndex) where T : class
  316. {
  317. return await FindList<T>(strSql, null, sort, isAsc, pageSize, pageIndex);
  318. }
  319. public async Task<(int total, IEnumerable<T>)> FindList<T>(string strSql, DbParameter[] dbParameter, string sort, bool isAsc, int pageSize, int pageIndex) where T : class
  320. {
  321. using (var dbConnection = dbContext.Database.GetDbConnection())
  322. {
  323. DbHelper dbHelper = new DbHelper(dbContext, dbConnection);
  324. StringBuilder sb = new StringBuilder();
  325. sb.Append(DatabasePageExtension.MySqlPageSql(strSql, dbParameter, sort, isAsc, pageSize, pageIndex));
  326. object tempTotal = await dbHelper.ExecuteScalarAsync(CommandType.Text, DatabasePageExtension.GetCountSql(strSql), dbParameter);
  327. int total = tempTotal.ParseToInt();
  328. if (total > 0)
  329. {
  330. var reader = await dbHelper.ExecuteReadeAsync(CommandType.Text, sb.ToString(), dbParameter);
  331. return (total, DatabasesExtension.IDataReaderToList<T>(reader));
  332. }
  333. else
  334. {
  335. return (total, new List<T>());
  336. }
  337. }
  338. }
  339. private async Task<(int total, IEnumerable<T> list)> FindList<T>(IQueryable<T> tempData, string sort, bool isAsc, int pageSize, int pageIndex)
  340. {
  341. tempData = DatabasesExtension.AppendSort<T>(tempData, sort, isAsc);
  342. var total = tempData.Count();
  343. if (total > 0)
  344. {
  345. tempData = tempData.Skip<T>(pageSize * (pageIndex - 1)).Take<T>(pageSize).AsQueryable();
  346. var list = await tempData.ToListAsync();
  347. return (total, list);
  348. }
  349. else
  350. {
  351. return (total, new List<T>());
  352. }
  353. }
  354. #endregion
  355. #region 数据源查询
  356. public async Task<DataTable> FindTable(string strSql)
  357. {
  358. return await FindTable(strSql, null);
  359. }
  360. public async Task<DataTable> FindTable(string strSql, DbParameter[] dbParameter)
  361. {
  362. using (var dbConnection = dbContext.Database.GetDbConnection())
  363. {
  364. var reader = await new DbHelper(dbContext, dbConnection).ExecuteReadeAsync(CommandType.Text, strSql, dbParameter);
  365. return DatabasesExtension.IDataReaderToDataTable(reader);
  366. }
  367. }
  368. public async Task<(int total, DataTable)> FindTable(string strSql, string sort, bool isAsc, int pageSize, int pageIndex)
  369. {
  370. return await FindTable(strSql, null, sort, isAsc, pageSize, pageIndex);
  371. }
  372. public async Task<(int total, DataTable)> FindTable(string strSql, DbParameter[] dbParameter, string sort, bool isAsc, int pageSize, int pageIndex)
  373. {
  374. using (var dbConnection = dbContext.Database.GetDbConnection())
  375. {
  376. DbHelper dbHelper = new DbHelper(dbContext, dbConnection);
  377. StringBuilder sb = new StringBuilder();
  378. sb.Append(DatabasePageExtension.MySqlPageSql(strSql, dbParameter, sort, isAsc, pageSize, pageIndex));
  379. object tempTotal = await dbHelper.ExecuteScalarAsync(CommandType.Text, "SELECT COUNT(1) FROM (" + strSql + ") T", dbParameter);
  380. int total = tempTotal.ParseToInt();
  381. if (total > 0)
  382. {
  383. var reader = await dbHelper.ExecuteReadeAsync(CommandType.Text, sb.ToString(), dbParameter);
  384. DataTable resultTable = DatabasesExtension.IDataReaderToDataTable(reader);
  385. return (total, resultTable);
  386. }
  387. else
  388. {
  389. return (total, new DataTable());
  390. }
  391. }
  392. }
  393. public async Task<object> FindObject(string strSql)
  394. {
  395. return await FindObject(strSql, null);
  396. }
  397. public async Task<object> FindObject(string strSql, DbParameter[] dbParameter)
  398. {
  399. using (var dbConnection = dbContext.Database.GetDbConnection())
  400. {
  401. return await new DbHelper(dbContext, dbConnection).ExecuteScalarAsync(CommandType.Text, strSql, dbParameter);
  402. }
  403. }
  404. public async Task<T> FindObject<T>(string strSql, DbParameter[] dbParameter = null) where T : class
  405. {
  406. var list = await dbContext.SqlQuery<T>(strSql, dbParameter);
  407. return list.FirstOrDefault();
  408. }
  409. #endregion
  410. }
  411. }