DB.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. using Microsoft.EntityFrameworkCore;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Transactions;
  6. namespace DBHelper
  7. {
  8. public class Db2 : IDisposable
  9. {
  10. public static Type DefaultDbContextType { get; private set; }
  11. private static readonly object LockObj = new object();
  12. public static T Do<T>(Func<Db2, T> func)
  13. {
  14. lock (LockObj)
  15. {
  16. using var db = new Db2();
  17. try
  18. {
  19. var res = func(db);
  20. db.Commit();
  21. return res;
  22. }
  23. catch (EntityValidationException ex)
  24. {
  25. var qty = ex.EntityValidationErrors.Count();
  26. var info = ex.EntityValidationErrors.First();
  27. var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? "");
  28. Console.WriteLine(msg);
  29. throw new Exception(msg);
  30. }
  31. }
  32. }
  33. public static void Do(Action<Db2> act)
  34. {
  35. Do(db =>
  36. {
  37. act(db);
  38. return 1;
  39. });
  40. }
  41. public static void SetDefaultDbContextType(Type dbContextType)
  42. {
  43. DefaultDbContextType = dbContextType;
  44. }
  45. public static void SetDefaultDbContextType<T>()
  46. {
  47. SetDefaultDbContextType(typeof(T));
  48. }
  49. private Dictionary<Type, DbContext> _contexts = new Dictionary<Type, DbContext>();
  50. public T Context<T>() where T : DbContext
  51. {
  52. return (T)Context(typeof(T));
  53. }
  54. public DbContext Default
  55. {
  56. get
  57. {
  58. if (DefaultDbContextType == null)
  59. throw new Exception("请先设置默认数据库,调用静态方法SetDefaultDbContextType()");
  60. return Context(DefaultDbContextType);
  61. }
  62. }
  63. public DbContext Context(Type type)
  64. {
  65. if (_contexts.ContainsKey(type))
  66. return _contexts[type];
  67. else
  68. {
  69. var ctx = Activator.CreateInstance(type) as DbContext;
  70. ctx.Database.BeginTransaction();
  71. _contexts.Add(type, ctx);
  72. return ctx;
  73. }
  74. }
  75. private void Commit()
  76. {
  77. Exception exception = null;
  78. try
  79. {
  80. foreach (var ctx in _contexts.Values)
  81. {
  82. ctx.SaveChanges();
  83. }
  84. }
  85. catch (EntityValidationException ex)
  86. {
  87. var qty = ex.EntityValidationErrors.Count();
  88. var info = ex.EntityValidationErrors.First();
  89. var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? "");
  90. Console.WriteLine(msg);
  91. exception = new Exception(msg);
  92. }
  93. catch (Exception ex)
  94. {
  95. exception = ex.GetBaseException();
  96. }
  97. foreach (var ctx in _contexts.Values)
  98. {
  99. try
  100. {
  101. if (exception == null)
  102. ctx.Database.CurrentTransaction!.Commit();
  103. else
  104. {
  105. ctx.Database.CurrentTransaction!.Rollback();
  106. throw exception;
  107. }
  108. }
  109. finally
  110. {
  111. ctx.Dispose();
  112. }
  113. }
  114. }
  115. public void Dispose()
  116. {
  117. foreach (var ctx in _contexts.Values)
  118. ctx.Dispose();
  119. _contexts.Clear();
  120. _contexts = null;
  121. }
  122. }
  123. public class DB : IDisposable
  124. {
  125. private readonly List<DbContext> _contexts = new List<DbContext>();
  126. public static Type DefaultDbContextType { get; private set; }
  127. public static T Do<T>(Func<DB, T> func)
  128. {
  129. var transactionOptions = new TransactionOptions
  130. {
  131. IsolationLevel = IsolationLevel.ReadCommitted,
  132. Timeout = new TimeSpan(0, 2, 0)
  133. };
  134. using var trans = new TransactionScope(TransactionScopeOption.RequiresNew, transactionOptions);
  135. using var db = new DB();
  136. try
  137. {
  138. var res = func(db);
  139. trans.Complete();
  140. return res;
  141. }
  142. catch (EntityValidationException ex)
  143. {
  144. var qty = ex.EntityValidationErrors.Count();
  145. var info = ex.EntityValidationErrors.First();
  146. var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? "");
  147. Console.WriteLine(msg);
  148. throw new Exception(msg);
  149. }
  150. finally
  151. {
  152. db.Dispose();
  153. }
  154. }
  155. public static void Do(Action<DB> act)
  156. {
  157. Do(db =>
  158. {
  159. act(db);
  160. return 1;
  161. });
  162. }
  163. public static void SetDefaultDbContextType(Type dbContextType)
  164. {
  165. DefaultDbContextType = dbContextType;
  166. }
  167. public static void SetDefaultDbContextType<T>()
  168. {
  169. SetDefaultDbContextType(typeof(T));
  170. }
  171. public DbContext Default
  172. {
  173. get
  174. {
  175. if (DefaultDbContextType == null)
  176. throw new Exception("请先设置默认数据库,调用静态方法SetDefaultDbContextType()");
  177. return Context(DefaultDbContextType);
  178. }
  179. }
  180. public DbContext Context(Type type)
  181. {
  182. var ctx = _contexts.FirstOrDefault(v => v.GetType() == type);
  183. if (ctx != null) return ctx;
  184. ctx = Activator.CreateInstance(type) as DbContext;
  185. _contexts.Add(ctx);
  186. return ctx;
  187. }
  188. public DbContext Context<TDbContext>()
  189. {
  190. return Context(typeof(TDbContext));
  191. }
  192. public void Dispose()
  193. {
  194. foreach (var ctx in _contexts)
  195. {
  196. ctx.Dispose();
  197. }
  198. _contexts.Clear();
  199. }
  200. }
  201. public class DB<TContext> where TContext : DbContext
  202. {
  203. public static IEnumerable<Type> EntityTypes
  204. {
  205. get
  206. {
  207. var ps = typeof(TContext).GetProperties().Where(v => v.PropertyType.Name == "DbSet`1").ToArray();
  208. var ts = ps.Select(v => v.PropertyType.GenericTypeArguments[0]).ToArray();
  209. return ts;
  210. }
  211. }
  212. /// <summary>
  213. /// 单数据库事务
  214. /// </summary>
  215. /// <typeparam name="TR"></typeparam>
  216. /// <param name="func"></param>
  217. /// <returns></returns>
  218. public static T Do<T>(Func<TContext, T> func)
  219. {
  220. using var ctx = Activator.CreateInstance<TContext>();
  221. var trans = ctx.Database.BeginTransaction(System.Data.IsolationLevel.Serializable);
  222. try
  223. {
  224. try
  225. {
  226. var result = func(ctx);
  227. ctx.SaveChanges();
  228. trans.Commit();
  229. return result;
  230. }
  231. catch (Exception ex)
  232. {
  233. trans.Rollback();
  234. throw ex.GetBaseException();
  235. }
  236. }
  237. catch (EntityValidationException ex)
  238. {
  239. var qty = ex.EntityValidationErrors.Count();
  240. var info = ex.EntityValidationErrors.First();
  241. var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? "");
  242. Console.WriteLine(msg);
  243. throw new Exception(msg);
  244. }
  245. }
  246. /// <summary>
  247. /// 单数据库事务
  248. /// </summary>
  249. /// <param name="act"></param>
  250. public static void Do(Action<TContext> act)
  251. {
  252. Do(ctx =>
  253. {
  254. act(ctx);
  255. return 1;
  256. });
  257. }
  258. }
  259. public class DB<TContext1, TContext2> where TContext1 : DbContext where TContext2 : DbContext
  260. {
  261. public static T Do<T>(Func<TContext1, TContext2, T> func)
  262. {
  263. using var ctx = Activator.CreateInstance<TContext1>();
  264. using var ctx2 = Activator.CreateInstance<TContext2>();
  265. var trans = ctx.Database.BeginTransaction(System.Data.IsolationLevel.Serializable);
  266. var trans2 = ctx2.Database.BeginTransaction(System.Data.IsolationLevel.Serializable);
  267. try
  268. {
  269. try
  270. {
  271. var result = func(ctx, ctx2);
  272. ctx.SaveChanges();
  273. ctx2.SaveChanges();
  274. trans.Commit();
  275. trans2.Commit();
  276. return result;
  277. }
  278. catch (Exception ex)
  279. {
  280. trans.Rollback();
  281. trans2.Rollback();
  282. throw ex.GetBaseException();
  283. }
  284. }
  285. catch (EntityValidationException ex)
  286. {
  287. var qty = ex.EntityValidationErrors.Count();
  288. var info = ex.EntityValidationErrors.First();
  289. var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? "");
  290. Console.WriteLine(msg);
  291. throw new Exception(msg);
  292. }
  293. }
  294. public static void Do(Action<TContext1, TContext2> act)
  295. {
  296. Do((ctx, ctx2) =>
  297. {
  298. act(ctx, ctx2);
  299. return 1;
  300. });
  301. }
  302. }
  303. public class DB<TContext1, TContext2, TContext3> where TContext1 : DbContext where TContext2 : DbContext where TContext3 : DbContext
  304. {
  305. public static T Do<T>(Func<TContext1, TContext2, TContext3, T> func)
  306. {
  307. using var ctx = Activator.CreateInstance<TContext1>();
  308. using var ctx2 = Activator.CreateInstance<TContext2>();
  309. using var ctx3 = Activator.CreateInstance<TContext3>();
  310. var trans = ctx.Database.BeginTransaction(System.Data.IsolationLevel.Serializable);
  311. var trans2 = ctx2.Database.BeginTransaction(System.Data.IsolationLevel.Serializable);
  312. var trans3 = ctx3.Database.BeginTransaction(System.Data.IsolationLevel.Serializable);
  313. try
  314. {
  315. try
  316. {
  317. var result = func(ctx, ctx2, ctx3);
  318. ctx.SaveChanges();
  319. ctx2.SaveChanges();
  320. ctx3.SaveChanges();
  321. trans.Commit();
  322. trans2.Commit();
  323. trans3.Commit();
  324. return result;
  325. }
  326. catch (Exception ex)
  327. {
  328. trans.Rollback();
  329. trans2.Rollback();
  330. trans3.Rollback();
  331. throw ex.GetBaseException();
  332. }
  333. }
  334. catch (EntityValidationException ex)
  335. {
  336. var qty = ex.EntityValidationErrors.Count();
  337. var info = ex.EntityValidationErrors.First();
  338. var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? "");
  339. Console.WriteLine(msg);
  340. throw new Exception(msg);
  341. }
  342. }
  343. public static void Do(Action<TContext1, TContext2, TContext3> act)
  344. {
  345. Do((ctx, ctx2, ctx3) =>
  346. {
  347. act(ctx, ctx2, ctx3);
  348. return 1;
  349. });
  350. }
  351. }
  352. }