using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Transactions; namespace DBHelper { public class Db2 : IDisposable { public static Type DefaultDbContextType { get; private set; } private static readonly object LockObj = new object(); public static T Do(Func func) { lock (LockObj) { using var db = new Db2(); try { var res = func(db); db.Commit(); return res; } catch (EntityValidationException ex) { var qty = ex.EntityValidationErrors.Count(); var info = ex.EntityValidationErrors.First(); var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? ""); Console.WriteLine(msg); throw new Exception(msg); } } } public static void Do(Action act) { Do(db => { act(db); return 1; }); } public static void SetDefaultDbContextType(Type dbContextType) { DefaultDbContextType = dbContextType; } public static void SetDefaultDbContextType() { SetDefaultDbContextType(typeof(T)); } private Dictionary Contexts = new Dictionary(); public T Context() where T : DbContext { return (T)Context(typeof(T)); } public DbContext Default { get { if (DefaultDbContextType == null) throw new Exception("请先设置默认数据库,调用静态方法SetDefaultDbContextType()"); return Context(DefaultDbContextType); } } public DbContext Context(Type type) { if (Contexts.ContainsKey(type)) return Contexts[type]; else { var ctx = Activator.CreateInstance(type) as DbContext; ctx.Database.BeginTransaction(); Contexts.Add(type, ctx); return ctx; } } private void Commit() { Exception exception = null; try { foreach (var ctx in Contexts.Values) { ctx.SaveChanges(); } } catch (EntityValidationException ex) { var qty = ex.EntityValidationErrors.Count(); var info = ex.EntityValidationErrors.First(); var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? ""); Console.WriteLine(msg); exception = new Exception(msg); } catch (Exception ex) { exception = ex.GetBaseException(); } foreach (var ctx in Contexts.Values) { try { if (exception == null) ctx.Database.CurrentTransaction!.Commit(); else { ctx.Database.CurrentTransaction!.Rollback(); throw exception; } } finally { ctx.Dispose(); } } } public void Dispose() { foreach (var ctx in Contexts.Values) ctx.Dispose(); Contexts.Clear(); Contexts = null; } } public class DB : IDisposable { private readonly List _contexts = new List(); public static Type DefaultDbContextType { get; private set; } public static T Do(Func func) { var transactionOptions = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 2, 0) }; using var trans = new TransactionScope(TransactionScopeOption.RequiresNew, transactionOptions); using var db = new DB(); try { var res = func(db); trans.Complete(); return res; } catch (EntityValidationException ex) { var qty = ex.EntityValidationErrors.Count(); var info = ex.EntityValidationErrors.First(); var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? ""); Console.WriteLine(msg); throw new Exception(msg); } finally { db.Dispose(); } } public static void Do(Action act) { Do(db => { act(db); return 1; }); } public static void SetDefaultDbContextType(Type dbContextType) { DefaultDbContextType = dbContextType; } public static void SetDefaultDbContextType() { SetDefaultDbContextType(typeof(T)); } public DbContext Default { get { if (DefaultDbContextType == null) throw new Exception("请先设置默认数据库,调用静态方法SetDefaultDbContextType()"); return Context(DefaultDbContextType); } } public DbContext Context(Type type) { var ctx = _contexts.FirstOrDefault(v => v.GetType() == type); if (ctx != null) return ctx; ctx = Activator.CreateInstance(type) as DbContext; _contexts.Add(ctx); return ctx; } public DbContext Context() { return Context(typeof(TDbContext)); } public void Dispose() { foreach (var ctx in _contexts) { ctx.Dispose(); } _contexts.Clear(); } } public class DB where TContext : DbContext { public static IEnumerable EntityTypes { get { var ps = typeof(TContext).GetProperties().Where(v => v.PropertyType.Name == "DbSet`1").ToArray(); var ts = ps.Select(v => v.PropertyType.GenericTypeArguments[0]).ToArray(); return ts; } } /// /// 单数据库事务 /// /// /// /// public static T Do(Func func) { using var ctx = Activator.CreateInstance(); var trans = ctx.Database.BeginTransaction(System.Data.IsolationLevel.Serializable); try { try { var result = func(ctx); ctx.SaveChanges(); trans.Commit(); return result; } catch (Exception ex) { trans.Rollback(); throw ex.GetBaseException(); } } catch (EntityValidationException ex) { var qty = ex.EntityValidationErrors.Count(); var info = ex.EntityValidationErrors.First(); var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? ""); Console.WriteLine(msg); throw new Exception(msg); } } /// /// 单数据库事务 /// /// public static void Do(Action act) { Do(ctx => { act(ctx); return 1; }); } } public class DB where TContext1 : DbContext where TContext2 : DbContext { public static T Do(Func func) { using var ctx = Activator.CreateInstance(); using var ctx2 = Activator.CreateInstance(); var trans = ctx.Database.BeginTransaction(System.Data.IsolationLevel.Serializable); var trans2 = ctx2.Database.BeginTransaction(System.Data.IsolationLevel.Serializable); try { try { var result = func(ctx, ctx2); ctx.SaveChanges(); ctx2.SaveChanges(); trans.Commit(); trans2.Commit(); return result; } catch (Exception ex) { trans.Rollback(); trans2.Rollback(); throw ex.GetBaseException(); } } catch (EntityValidationException ex) { var qty = ex.EntityValidationErrors.Count(); var info = ex.EntityValidationErrors.First(); var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? ""); Console.WriteLine(msg); throw new Exception(msg); } } public static void Do(Action act) { Do((ctx, ctx2) => { act(ctx, ctx2); return 1; }); } } public class DB where TContext1 : DbContext where TContext2 : DbContext where TContext3 : DbContext { public static T Do(Func func) { using var ctx = Activator.CreateInstance(); using var ctx2 = Activator.CreateInstance(); using var ctx3 = Activator.CreateInstance(); var trans = ctx.Database.BeginTransaction(System.Data.IsolationLevel.Serializable); var trans2 = ctx2.Database.BeginTransaction(System.Data.IsolationLevel.Serializable); var trans3 = ctx3.Database.BeginTransaction(System.Data.IsolationLevel.Serializable); try { try { var result = func(ctx, ctx2, ctx3); ctx.SaveChanges(); ctx2.SaveChanges(); ctx3.SaveChanges(); trans.Commit(); trans2.Commit(); trans3.Commit(); return result; } catch (Exception ex) { trans.Rollback(); trans2.Rollback(); trans3.Rollback(); throw ex.GetBaseException(); } } catch (EntityValidationException ex) { var qty = ex.EntityValidationErrors.Count(); var info = ex.EntityValidationErrors.First(); var msg = "有" + qty + "条数据验证失败,首条错误信息:\n" + string.Join("\n", info.MemberNames) + "\n" + (info.ErrorMessage ?? ""); Console.WriteLine(msg); throw new Exception(msg); } } public static void Do(Action act) { Do((ctx, ctx2, ctx3) => { act(ctx, ctx2, ctx3); return 1; }); } } }