Мое приложение увеличивается, и до сих пор у меня есть один MyDbContext
, который имеет все необходимые мне таблицы в моем приложении. Я хочу (ради обзора) разделить их на несколько DbContext
, например MainDbContext
, EstateModuleDbContext
, AnotherModuleDbContext
и UserDbContext
.Использование нескольких DbContexts с общим хранилищем и единицей работы
Я не уверен, как это делается, наверное, как я сейчас, используя инъекции зависимых пакетов (Ninject), чтобы поместить мой DbContext на моем UnitOfWork классе, как:
kernel.Bind(typeof(IUnitOfWork)).To(typeof(UnitOfWork<MyDbContext>));
Должен ли я отказаться от этого подхода с инъекцией зависимостей и явной установить DbContext
Я хочу использовать на свои услуги, как:
private readonly EstateService _estateService;
public HomeController()
{
IUnitOfWork uow = new UnitOfWork<MyDbContext>();
_estateService = new EstateService(uow);
}
Вместо:
private readonly EstateService _estateService;
public HomeController(IUnitOfWork uow)
{
_estateService = new EstateService(uow);
}
Или это еще один подход? Также, как побочный вопрос, мне не нравится передавать uow
на мой сервис - есть ли другой (лучший) подход?
Код
Я это IDbContext и MyDbContext:
public interface IDbContext
{
DbSet<T> Set<T>() where T : class;
DbEntityEntry<T> Entry<T>(T entity) where T : class;
int SaveChanges();
void Dispose();
}
public class MyDbContext : DbContext, IDbContext
{
public DbSet<Table1> Table1 { get; set; }
public DbSet<Table2> Table1 { get; set; }
public DbSet<Table3> Table1 { get; set; }
public DbSet<Table4> Table1 { get; set; }
public DbSet<Table5> Table1 { get; set; }
/* and so on */
static MyDbContext()
{
Database.SetInitializer<MyDbContext>(new CreateDatabaseIfNotExists<MyDbContext>());
}
public MyDbContext()
: base("MyDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
Тогда у меня есть эта IRepository и реализация:
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
void Add(T entity);
void Delete(T entity);
void DeleteAll(IEnumerable<T> entity);
void Update(T entity);
bool Any();
}
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDbContext _context;
private readonly IDbSet<T> _dbset;
public Repository(IDbContext context)
{
_context = context;
_dbset = context.Set<T>();
}
public virtual IQueryable<T> GetAll()
{
return _dbset;
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
var entry = _context.Entry(entity);
entry.State = EntityState.Deleted;
_dbset.Remove(entity);
}
public virtual void DeleteAll(IEnumerable<T> entity)
{
foreach (var ent in entity)
{
var entry = _context.Entry(ent);
entry.State = EntityState.Deleted;
_dbset.Remove(ent);
}
}
public virtual void Update(T entity)
{
var entry = _context.Entry(entity);
_dbset.Attach(entity);
entry.State = EntityState.Modified;
}
public virtual bool Any()
{
return _dbset.Any();
}
}
И в IUnitOfWor к и РЕАЛИЗАЦИЯ, который обрабатывает работу с DbContext
public interface IUnitOfWork : IDisposable
{
IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
void Save();
}
public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new()
{
private readonly IDbContext _ctx;
private readonly Dictionary<Type, object> _repositories;
private bool _disposed;
public UnitOfWork()
{
_ctx = new TContext();
_repositories = new Dictionary<Type, object>();
_disposed = false;
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
// Checks if the Dictionary Key contains the Model class
if (_repositories.Keys.Contains(typeof(TEntity)))
{
// Return the repository for that Model class
return _repositories[typeof(TEntity)] as IRepository<TEntity>;
}
// If the repository for that Model class doesn't exist, create it
var repository = new Repository<TEntity>(_ctx);
// Add it to the dictionary
_repositories.Add(typeof(TEntity), repository);
return repository;
}
public void Save()
{
_ctx.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (this._disposed) return;
if (disposing)
{
_ctx.Dispose();
}
this._disposed = true;
}
}
Существуют ли логические швы для разделения данных по нескольким dbcontexts? Если вы это сделаете, вы не сможете иметь свойства навигации или коллекции, которые пересекают контексты (например, вы не можете выполнять отношения EF между объектом в MainDbContext и другим объектом в UsersDbContext). – danludwig
В чем причина разделения контекста? Также, если вы разделите их, вы не сможете использовать DI. Мне также не понравился ваш блок работы с репозиторием в нем (словарь вещь) –
Я буду иметь несколько модулей в своем приложении и просто не загрязнять MyDbContext с большим количеством модулей DbSets. Может быть, я должен просто проигнорировать это? – janhartmann