Entity Framework usando un patrón de repositorio, unidad de trabajo y unidad
Usando una combinación proporcionada poreste ejemplo yesta implementación Estoy tratando de crear una solución que separa laUnitOfWork
clase de los repositorios individuales, ya que violan el principio abierto-cerrado, ya que cada vez que agregue un nuevo repositorio, tendrá que modificar elUnitOfWork
clase. Estoy usando Unity como el contenedor de IoC para conectar las dependencias.
El problema que tengo es que al cablear automáticamente elUnitOfWork
, IDbContext
y los repositorios (IEmployeeRepository
yICustomerRepository
) utilizando Unity, los repositorios se inyectarán con instancias separadas deUnitOfWork
, que, por supuesto, derrota al propósito. Necesito compartir el contexto a través de los repositorios, y parece que me falta una pieza para este rompecabezas: en este momento (ver Capa de servicio) laUnitOfWork
será una instancia diferente de laUnitOfWork
Para cada uno de los repositorios.
¿Cómo inyectar elIUnitOfWork
en la capa de servicio y pasar esto instanciadocompartido UnitOfWork
¿Clase a los repositorios respectivos, usando la unidad y la inyección de dependencia?
Aquí está mi solución propuesta (fabricada):
Repositorios
public interface IRepository<TEntity> where TEntity : class
{
TEntity Create();
// omitted for brevity
}
public class Repository<TEntity> : IRepository<TEntity>
where TEntity : class
{
private readonly DbContext _context;
public Repository(IUnitOfWork uow)
{
_context = uow.Context;
}
public virtual TEntity Create(TEntity entity)
{
return _context.Set<TEntity>().Add(entity);
}
// omitted for brevity
}
public interface IEmployeeRepository : IRepository<Employee>
{
}
public interface ICustomerRepository : IRepository<Customer>
{
}
public class EmployeeRepository : Repository<Employee>
{
public EmployeeRepository(IUnitOfWork uow)
: base(uow)
{
}
}
public class CustomerRepository : Repository<Customer>
{
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;
}
}
Unidad de trabajo
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);
}
}
Servicio
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();
}
}