Created
June 21, 2018 21:18
-
-
Save vendettamit/73a7c9c9344adaa1cb73c4e48f7d2df1 to your computer and use it in GitHub Desktop.
Generic implementation of Unit of work. Created for StackOverflow question here: https://stackoverflow.com/questions/50976573/how-do-i-change-my-unit-of-work-to-allow-multiple-dbcontexts/50977544#50977544
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface IUnitOfWork<TContext> where TContext: DbContext, new() | |
{ | |
void Commit(); | |
} | |
public interface IDbFactory<TContext> : IDisposable where TContext: DbContext, new() | |
{ | |
TContext Init(); | |
} | |
public class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext: DbContext, new() | |
{ | |
private readonly IDbFactory<TContext> _dbFactory; | |
private TContext _dbContext; | |
public UnitOfWork(IDbFactory<TContext> dbFactory) | |
{ | |
this._dbFactory = dbFactory; | |
} | |
public TContext DbContext | |
{ | |
get { return _dbContext ?? (_dbContext = _dbFactory.Init()); } | |
} | |
public void Commit() | |
{ | |
DbContext.SaveChanges(); | |
} | |
} | |
public class DbFactory<TContext> : Disposable, IDbFactory<TContext> where TContext: DbContext, new() | |
{ | |
TContext _dbContext; | |
public TContext Init() | |
{ | |
return _dbContext ?? (_dbContext = new TContext()); | |
} | |
protected override void DisposeCore() | |
{ | |
_dbContext?.Dispose(); | |
} | |
} | |
public abstract class RepositoryBase<T, TContext> where T : class where TContext: DbContext, new() | |
{ | |
#region Properties | |
private TContext _dataContext; | |
private readonly IDbSet<T> _dbSet; | |
protected IDbFactory<TContext> DbFactory | |
{ | |
get; | |
private set; | |
} | |
protected TContext DbContext | |
{ | |
get { return _dataContext ?? (_dataContext = this.DbFactory.Init()); } | |
} | |
#endregion | |
protected RepositoryBase(IDbFactory<TContext> dbFactory) | |
{ | |
DbFactory = dbFactory; | |
_dbSet = DbContext.Set<T>(); | |
} | |
#region Implementation | |
public virtual void Add(T entity) | |
{ | |
_dbSet.Add(entity); | |
} | |
public virtual void Update(T entity) | |
{ | |
_dbSet.Attach(entity); | |
_dataContext.Entry(entity).State = System.Data.Entity.EntityState.Modified; | |
} | |
public virtual void Delete(T entity) | |
{ | |
_dbSet.Remove(entity); | |
} | |
public virtual void Delete(Expression<Func<T, bool>> where) | |
{ | |
IEnumerable<T> objects = _dbSet.Where<T>(where).AsEnumerable(); | |
foreach (T obj in objects) | |
_dbSet.Remove(obj); | |
} | |
public virtual T GetById(int id) | |
{ | |
return _dbSet.Find(id); | |
} | |
public virtual IEnumerable<T> GetAll() | |
{ | |
return _dbSet.ToList(); | |
} | |
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where) | |
{ | |
return _dbSet.Where(where).ToList(); | |
} | |
public T Get(Expression<Func<T, bool>> where) | |
{ | |
return _dbSet.Where(where).FirstOrDefault<T>(); | |
} | |
#endregion | |
} | |
public interface IRepository<T> where T : class | |
{ | |
// Marks an entity as new | |
void Add(T entity); | |
// Marks an entity as modified | |
void Update(T entity); | |
// Marks an entity to be removed | |
void Delete(T entity); | |
void Delete(Expression<Func<T, bool>> where); | |
// Get an entity by int id | |
T GetById(int id); | |
// Get an entity using delegate | |
T Get(Expression<Func<T, bool>> where); | |
// Gets all entities of type T | |
IEnumerable<T> GetAll(); | |
// Gets entities using delegate | |
IEnumerable<T> GetMany(Expression<Func<T, bool>> where); | |
} | |
public class AppSetting { } | |
public interface IAppSettingService { } | |
public class ApplicationUser : IdentityUser { } | |
public interface IAppSettingRepository : IRepository<AppSetting> | |
{ | |
void UpdateAppSetting(AppSetting appSetting); | |
} | |
public class AppSettingRepository : RepositoryBase<AppSetting, WilMpeContext>, IAppSettingRepository | |
{ | |
public AppSettingRepository(IDbFactory<WilMpeContext> dbFactory) | |
: base(dbFactory) { } | |
//an example of how I do something in the database. See I use DbContext from RepositoryBase | |
public void UpdateAppSetting(AppSetting appSetting) | |
{ | |
DbContext.Entry(appSetting).State = System.Data.Entity.EntityState.Modified; | |
} | |
} | |
public class AppSettingService : IAppSettingService | |
{ | |
private readonly IAppSettingRepository _appSettingRepository; | |
private readonly IUnitOfWork<WilMpeContext> _unitOfWork; | |
public AppSettingService(IAppSettingRepository appSettingRepository, | |
IUnitOfWork<WilMpeContext> unitOfWork) | |
{ | |
_appSettingRepository = appSettingRepository; | |
_unitOfWork = unitOfWork; | |
} | |
//call repository to do database stuff and then commit changes | |
public void UpdateAppSetting(AppSetting appSetting) | |
{ | |
_appSettingRepository.UpdateAppSetting(appSetting); | |
_unitOfWork.Commit(); | |
} | |
} | |
public class WilMpeContext : IdentityDbContext<ApplicationUser> | |
{ | |
public WilMpeContext() | |
: base("name=DefaultConnection", throwIfV1Schema: false) { } | |
public IDbSet<AppSetting> AppSettings { get; set; } | |
//the rest of the tables were removed for brevity | |
public static WilMpeContext Create() | |
{ | |
return new WilMpeContext(); | |
} | |
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder) | |
{ | |
base.OnModelCreating(modelBuilder); | |
} | |
} | |
public class Disposable : IDisposable | |
{ | |
private bool isDisposed; | |
~Disposable() | |
{ | |
Dispose(false); | |
} | |
public void Dispose() | |
{ | |
Dispose(true); | |
GC.SuppressFinalize(this); | |
} | |
private void Dispose(bool disposing) | |
{ | |
if (!isDisposed && disposing) | |
{ | |
DisposeCore(); | |
} | |
isDisposed = true; | |
} | |
// Ovveride this to dispose custom objects | |
protected virtual void DisposeCore() | |
{ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment