Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- IUnitOfWork.cs
- public interface IUnitOfWork : IDisposable
- {
- DbContext Context { get; }
- bool HasChanges();
- bool IsInTransaction();
- void ExecuteInTransaction(Action action);
- void Commit();
- IQueryable<T> Query<T>() where T : class, IEntity;
- IQueryable<T> Query<T>(Expression<Func<T, bool>> filter) where T : class, IEntity;
- IQueryable<T> GetQueryable<T>() where T : class, IEntity;
- }
- public class UnitOfWork : IUnitOfWork
- {
- private IDbContextTransaction _transaction;
- public DbContext Context { get; private set; }
- public UnitOfWork(DbContext context)
- {
- context.EnsureNotNull();
- Context = context;
- }
- public event EventHandler<EntityEventArgs> EntityUpdated;
- public bool IsInTransaction()
- {
- return _transaction != null;
- }
- public void ExecuteInTransaction(Action action)
- {
- var isAlreadyInTransaction = IsInTransaction();
- try
- {
- if (!isAlreadyInTransaction) BeginTransaction();
- action();
- if (!isAlreadyInTransaction) CommitTransaction();
- }
- catch (Exception)
- {
- if (!isAlreadyInTransaction)
- RollbackTransaction();
- throw;
- }
- }
- public bool HasChanges()
- {
- return GetChanges().Any();
- }
- public async Task CommitAsync()
- {
- await CommitAsync(true);
- }
- public async Task CommitAsync(bool skipCacheUpdate)
- {
- try
- {
- // collect entries to fire events after save changes
- var modifiedEntries = !skipCacheUpdate ? GetChanges().ToArray() : null;
- await Context.SaveChangesAsync();
- // fire entries updated
- if (modifiedEntries != null && modifiedEntries.Any() && EntityUpdated != null)
- {
- var modifiedTypes = modifiedEntries.Select(e => e.GetType()).Distinct().ToArray();
- EntityUpdated(this, new EntityEventArgs(modifiedTypes));
- }
- }
- catch (DbUpdateException ex)
- {
- if (IsInTransaction())
- RollbackTransaction();
- TryRejectChanges();
- throw new AppException("SaveChanges failed", ex);
- }
- }
- public void Commit()
- {
- try
- {
- Context.SaveChanges();
- }
- catch (DbUpdateException ex)
- {
- if (IsInTransaction())
- RollbackTransaction();
- TryRejectChanges();
- throw new AppException("SaveChanges failed", ex);
- }
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- protected virtual void Dispose(bool disposing)
- {
- if (!disposing)
- return;
- if (IsInTransaction())
- RollbackTransaction();
- if (Context == null)
- return;
- Context.Dispose();
- Context = null;
- }
- ~UnitOfWork()
- {
- Dispose(false);
- }
- public IRepository<T> Repository<T>() where T : class, IEntity
- {
- return new Repository<T>(this);
- }
- public IQueryable<T> GetQueryable<T>() where T : class, IEntity
- {
- return Context.Set<T>().AsQueryable();
- }
- private void BeginTransaction()
- {
- if (IsInTransaction())
- throw new AppException("Already in transaction.");
- _transaction = Context.Database.BeginTransaction();
- }
- private void CommitTransaction()
- {
- if (!IsInTransaction())
- throw new AppException("Not in transaction.");
- _transaction.Commit();
- _transaction.Dispose();
- _transaction = null;
- }
- private void RollbackTransaction()
- {
- if (!IsInTransaction())
- throw new AppException("Not in transaction");
- _transaction.Rollback();
- _transaction.Dispose();
- _transaction = null;
- }
- private void TryRejectChanges()
- {
- try
- {
- foreach (var entry in Context.ChangeTracker.Entries())
- {
- switch (entry.State)
- {
- case EntityState.Modified:
- entry.CurrentValues.SetValues(entry.OriginalValues);
- entry.State = EntityState.Unchanged;
- break;
- case EntityState.Deleted:
- entry.State = EntityState.Unchanged;
- break;
- case EntityState.Added:
- entry.State = EntityState.Detached;
- break;
- }
- }
- }
- catch (Exception ex)
- {
- Debug.WriteLine("TryRejectChanges silently failed: {0}", ex.Message);
- }
- }
- private IEnumerable<object> GetChanges()
- {
- return Context.ChangeTracker.Entries()
- .Where(t =>
- t.State == EntityState.Added || t.State == EntityState.Modified ||
- t.State == EntityState.Deleted)
- .Select(e => e.Entity);
- }
- public IQueryable<T> Query<T>() where T : class, IEntity
- {
- return Context.Set<T>();
- }
- public IQueryable<T> Query<T>(Expression<Func<T, bool>> filter) where T : class, IEntity
- {
- return Context.Set<T>().Where(filter);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement