Advertisement
uraharadono

Stripped UoW

Oct 27th, 2021
232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.16 KB | None | 0 0
  1. IUnitOfWork.cs
  2.     public interface IUnitOfWork : IDisposable
  3.     {
  4.         DbContext Context { get; }
  5.  
  6.         bool HasChanges();
  7.         bool IsInTransaction();
  8.         void ExecuteInTransaction(Action action);
  9.  
  10.         void Commit();
  11.  
  12.         IQueryable<T> Query<T>() where T : class, IEntity;
  13.         IQueryable<T> Query<T>(Expression<Func<T, bool>> filter) where T : class, IEntity;
  14.         IQueryable<T> GetQueryable<T>() where T : class, IEntity;
  15.     }
  16.  
  17. public class UnitOfWork : IUnitOfWork
  18.     {
  19.         private IDbContextTransaction _transaction;
  20.  
  21.         public DbContext Context { get; private set; }
  22.  
  23.         public UnitOfWork(DbContext context)
  24.         {
  25.             context.EnsureNotNull();
  26.             Context = context;
  27.         }
  28.  
  29.         public event EventHandler<EntityEventArgs> EntityUpdated;
  30.  
  31.         public bool IsInTransaction()
  32.         {
  33.             return _transaction != null;
  34.         }
  35.  
  36.         public void ExecuteInTransaction(Action action)
  37.         {
  38.             var isAlreadyInTransaction = IsInTransaction();
  39.  
  40.             try
  41.             {
  42.                 if (!isAlreadyInTransaction) BeginTransaction();
  43.                 action();
  44.                 if (!isAlreadyInTransaction) CommitTransaction();
  45.             }
  46.             catch (Exception)
  47.             {
  48.                 if (!isAlreadyInTransaction)
  49.                     RollbackTransaction();
  50.                 throw;
  51.             }
  52.         }
  53.  
  54.         public bool HasChanges()
  55.         {
  56.             return GetChanges().Any();
  57.         }
  58.  
  59.         public async Task CommitAsync()
  60.         {
  61.             await CommitAsync(true);
  62.         }
  63.  
  64.         public async Task CommitAsync(bool skipCacheUpdate)
  65.         {
  66.             try
  67.             {
  68.                 // collect entries to fire events after save changes
  69.                 var modifiedEntries = !skipCacheUpdate ? GetChanges().ToArray() : null;
  70.  
  71.                 await Context.SaveChangesAsync();
  72.  
  73.                 // fire entries updated
  74.                 if (modifiedEntries != null && modifiedEntries.Any() && EntityUpdated != null)
  75.                 {
  76.                     var modifiedTypes = modifiedEntries.Select(e => e.GetType()).Distinct().ToArray();
  77.                     EntityUpdated(this, new EntityEventArgs(modifiedTypes));
  78.                 }
  79.             }
  80.             catch (DbUpdateException ex)
  81.             {
  82.                 if (IsInTransaction())
  83.                     RollbackTransaction();
  84.  
  85.                 TryRejectChanges();
  86.                 throw new AppException("SaveChanges failed", ex);
  87.             }
  88.         }
  89.  
  90.         public void Commit()
  91.         {
  92.             try
  93.             {
  94.                 Context.SaveChanges();
  95.             }
  96.             catch (DbUpdateException ex)
  97.             {
  98.                 if (IsInTransaction())
  99.                     RollbackTransaction();
  100.  
  101.                 TryRejectChanges();
  102.                 throw new AppException("SaveChanges failed", ex);
  103.             }
  104.         }
  105.  
  106.         public void Dispose()
  107.         {
  108.             Dispose(true);
  109.             GC.SuppressFinalize(this);
  110.         }
  111.  
  112.         protected virtual void Dispose(bool disposing)
  113.         {
  114.             if (!disposing)
  115.                 return;
  116.  
  117.             if (IsInTransaction())
  118.                 RollbackTransaction();
  119.  
  120.             if (Context == null)
  121.                 return;
  122.  
  123.             Context.Dispose();
  124.             Context = null;
  125.         }
  126.  
  127.         ~UnitOfWork()
  128.         {
  129.             Dispose(false);
  130.         }
  131.  
  132.  
  133.         public IRepository<T> Repository<T>() where T : class, IEntity
  134.         {
  135.             return new Repository<T>(this);
  136.         }
  137.  
  138.  
  139.         public IQueryable<T> GetQueryable<T>() where T : class, IEntity
  140.         {
  141.             return Context.Set<T>().AsQueryable();
  142.         }
  143.  
  144.         private void BeginTransaction()
  145.         {
  146.             if (IsInTransaction())
  147.                 throw new AppException("Already in transaction.");
  148.  
  149.             _transaction = Context.Database.BeginTransaction();
  150.         }
  151.  
  152.         private void CommitTransaction()
  153.         {
  154.             if (!IsInTransaction())
  155.                 throw new AppException("Not in transaction.");
  156.  
  157.             _transaction.Commit();
  158.             _transaction.Dispose();
  159.             _transaction = null;
  160.         }
  161.  
  162.         private void RollbackTransaction()
  163.         {
  164.             if (!IsInTransaction())
  165.                 throw new AppException("Not in transaction");
  166.  
  167.             _transaction.Rollback();
  168.             _transaction.Dispose();
  169.             _transaction = null;
  170.         }
  171.  
  172.         private void TryRejectChanges()
  173.         {
  174.             try
  175.             {
  176.                 foreach (var entry in Context.ChangeTracker.Entries())
  177.                 {
  178.                     switch (entry.State)
  179.                     {
  180.                         case EntityState.Modified:
  181.                             entry.CurrentValues.SetValues(entry.OriginalValues);
  182.                             entry.State = EntityState.Unchanged;
  183.                             break;
  184.                         case EntityState.Deleted:
  185.                             entry.State = EntityState.Unchanged;
  186.                             break;
  187.                         case EntityState.Added:
  188.                             entry.State = EntityState.Detached;
  189.                             break;
  190.                     }
  191.                 }
  192.             }
  193.             catch (Exception ex)
  194.             {
  195.                 Debug.WriteLine("TryRejectChanges silently failed: {0}", ex.Message);
  196.             }
  197.         }
  198.  
  199.         private IEnumerable<object> GetChanges()
  200.         {
  201.             return Context.ChangeTracker.Entries()
  202.                 .Where(t =>
  203.                     t.State == EntityState.Added || t.State == EntityState.Modified ||
  204.                     t.State == EntityState.Deleted)
  205.                 .Select(e => e.Entity);
  206.         }
  207.  
  208.         public IQueryable<T> Query<T>() where T : class, IEntity
  209.         {
  210.             return Context.Set<T>();
  211.         }
  212.  
  213.         public IQueryable<T> Query<T>(Expression<Func<T, bool>> filter) where T : class, IEntity
  214.         {
  215.             return Context.Set<T>().Where(filter);
  216.         }
  217.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement