Entity Framework с использованием шаблона репозитория, единицы работы и единства
Используя комбинацию изэтот пример а такжеэта реализация Я пытаюсь создать решение, которое разделяетUnitOfWork
класс из отдельных репозиториев, так как они нарушают принцип Open-Closed, поскольку каждый раз, когда вы добавляете новый репозиторий, вам придется изменятьUnitOfWork
учебный класс. Я использую Unity в качестве контейнера IoC для подключения зависимостей.
Проблема в том, что при автоматическом подключенииUnitOfWork
IDbContext
и хранилища (IEmployeeRepository
а такжеICustomerRepository
) используя Unity, в репозитории будут добавлены отдельные экземплярыUnitOfWork
, что, конечно, побеждает цель. Мне нужно поделиться контекстом между репозиториями, и, похоже, мне не хватает части этой головоломки - на данный момент (см. Сервисный слой)UnitOfWork
экземпляр будет отличаться отUnitOfWork
для каждого из репозиториев.
Как сделать инъекциюIUnitOfWork
в сервисный уровень и передать этот экземпляробщий UnitOfWork
Класс для соответствующих репозиториев, используя Unity и внедрение зависимостей?
Вот'Мое предлагаемое (изготовленное) решение:
Хранилища
public interface IRepository where TEntity : class
{
TEntity Create();
// omitted for brevity
}
public class Repository : IRepository
where TEntity : class
{
private readonly DbContext _context;
public Repository(IUnitOfWork uow)
{
_context = uow.Context;
}
public virtual TEntity Create(TEntity entity)
{
return _context.Set().Add(entity);
}
// omitted for brevity
}
public interface IEmployeeRepository : IRepository
{
}
public interface ICustomerRepository : IRepository
{
}
public class EmployeeRepository : Repository
{
public EmployeeRepository(IUnitOfWork uow)
: base(uow)
{
}
}
public class CustomerRepository : Repository
{
public CustomerRepository(IUnitOfWork uow)
: base(uow)
{
}
}
DbContext Factory
public interface IDbContextFactory
{
DbContext GetContext();
}
public class DbContextFactory : IDbContextFactory
{
private readonly DbContext _context;
public DbContextFactory()
{
_context = new MyDbContext("ConnectionStringName");
}
public DbContext GetContext()
{
return _context;
}
}
Единица работы
public interface IUnitOfWork
{
void SaveChanges();
DbContext Context { get; }
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly DbContext _context;
private bool disposed = false;
public UnitOfWork(IDbContextFactory contextFactory)
{
_context = contextFactory.GetContext();
}
public void SaveChanges()
{
if (_context != null)
{
_context.SaveChanges();
}
}
public DbContext Context
{
get { return _context; }
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
_context.Dispose();
}
}
disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
обслуживание
public class CompanyService
{
private readonly IUnitOfWork _uow;
private readonly IEmployeeRepository _employeeRepository;
private readonly ICustomerRepository _customerRepository;
public CompanyService(IUnitOfWork uow, IEmployeeRepository employeeRepository, ICustomerRepository customerRepository)
{
_uow = uow;
_employeeRepository = employeeRepository;
_customerRepository = customerRepository;
}
// over-simplified example method
public void AddEmployeeAndCustomer()
{
_employeeRepository.Create(new Employee {Id = 1, Name = "Test Employee"});
_customerRepository.Create(new Customer { Id = 2, Name = "Test Customer" });
_uow.SaveChanges();
}
}