How do I update this code below to allow for multiple DbContexts? I searched other posts and I tried to make my unit of work and dbfactory classes accept a generic type but I had trouble with the RepositoryBase class, the repository, the service and tying it all together; I still struggle with generics in C#. Can anyone help me out?
DbFactory.cs
public class DbFactory : Disposable, IDbFactory
{
WilMpeContext _dbContext;
public WilMpeContext Init()
{
return _dbContext ?? (_dbContext = new WilMpeContext());
}
protected override void DisposeCore()
{
_dbContext?.Dispose();
}
}
Disposable.cs
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()
{
}
}
iDbFactory.cs
public interface IDbFactory : IDisposable
{
WilMpeContext Init();
}
IRepository.cs
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);
}
IUnitOfWork.cs
public interface IUnitOfWork
{
void Commit();
}
RepositoryBase.cs
public abstract class RepositoryBase<T> where T : class
{
#region Properties
private WilMpeContext _dataContext;
private readonly IDbSet<T> _dbSet;
protected IDbFactory DbFactory
{
get;
private set;
}
protected WilMpeContext DbContext
{
get { return _dataContext ?? (_dataContext = DbFactory.Init()); }
}
#endregion
protected RepositoryBase(IDbFactory 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 = 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
}
UnitOfWork.cs
public class UnitOfWork : IUnitOfWork
{
private readonly IDbFactory _dbFactory;
private WilMpeContext _dbContext;
public UnitOfWork(IDbFactory dbFactory)
{
this._dbFactory = dbFactory;
}
public WilMpeContext DbContext
{
get { return _dbContext ?? (_dbContext = _dbFactory.Init()); }
}
public void Commit()
{
DbContext.Commit();
}
}
WilMpeContext.cs - this is one of my DbContexts but now I need another and I'm not sure how to implement that with my existing design
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 virtual void Commit()
{
base.SaveChanges();
}
public static WilMpeContext Create()
{
return new WilMpeContext();
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
Here is how I setup the repository to use the unit of work. AppSetting is a table in my model:
public interface IAppSettingRepository : IRepository<AppSetting>
{
void UpdateAppSetting(AppSetting appSetting);
}
public class AppSettingRepository : RepositoryBase<AppSetting>,IAppSettingRepository
{
public AppSettingRepository(IDbFactory 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 = EntityState.Modified;
}
}
And this is my service:
public class AppSettingService : IAppSettingService
{
private readonly IAppSettingRepository _appSettingRepository;
private readonly IUnitOfWork _unitOfWork;
public AppSettingService(IAppSettingRepository appSettingRepository,
IUnitOfWork 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();
}
}