Луковая архитектура, единица работы и общий шаблон репозитория
Это первый раз, когда я внедряю более ориентированный на домен подход к проектированию. Я решил попробоватьЛуковая Архитектура поскольку он фокусируется на домене, а не на инфраструктуре / платформах / и т.д.
Чтобы абстрагироваться от Entity Framework, я создалобщий репозиторий сЕдиница работы реализация.
IRepository
а такжеIUnitOfWork
интерфейсы:
public interface IRepository
{
void Add(T item);
void Remove(T item);
IQueryable Query();
}
public interface IUnitOfWork : IDisposable
{
void SaveChanges();
}
Реализация Entity FrameworkIRepository
а также :IUnitOfWork
public class EntityFrameworkRepository : IRepository where T : class
{
private readonly DbSet dbSet;
public EntityFrameworkRepository(IUnitOfWork unitOfWork)
{
var entityFrameworkUnitOfWork = unitOfWork as EntityFrameworkUnitOfWork;
if (entityFrameworkUnitOfWork == null)
{
throw new ArgumentOutOfRangeException("Must be of type EntityFrameworkUnitOfWork");
}
dbSet = entityFrameworkUnitOfWork.GetDbSet();
}
public void Add(T item)
{
dbSet.Add(item);
}
public void Remove(T item)
{
dbSet.Remove(item);
}
public IQueryable Query()
{
return dbSet;
}
}
public class EntityFrameworkUnitOfWork : IUnitOfWork
{
private readonly DbContext context;
public EntityFrameworkUnitOfWork()
{
this.context = new CustomerContext();;
}
internal DbSet GetDbSet()
where T : class
{
return context.Set();
}
public void SaveChanges()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
Покупатель репозиторий:
public interface ICustomerRepository : IRepository
{
}
public class CustomerRepository : EntityFrameworkRepository, ICustomerRepository
{
public CustomerRepository(IUnitOfWork unitOfWork): base(unitOfWork)
{
}
}
ASP.NET MVC контроллер с использованием репозитория:
public class CustomerController : Controller
{
UnityContainer container = new UnityContainer();
public ActionResult List()
{
var unitOfWork = container.Resolve();
var customerRepository = container.Resolve();
return View(customerRepository.Query());
}
[HttpPost]
public ActionResult Create(Customer customer)
{
var unitOfWork = container.Resolve();
var customerRepository = container.Resolve();;
customerRepository.Add(customer);
unitOfWork.SaveChanges();
return RedirectToAction("List");
}
}
Внедрение зависимости с единицей:
container.RegisterType();
container.RegisterType();
Решение:
ПРОБЛЕМЫ?
Реализация репозитория (код EF) очень общая. Все это сидит в стороне отEntityFrameworkRepository
учебный класс. Конкретные репозитории моделей не содержат никакой этой логики. Это спасает меня от написания тонны избыточного кода, но, возможно, жертвует гибкостью?
ICustomerRepository
а такжеCustomerRepository
классы в основном пустые. Они просто для того, чтобы обеспечить абстракцию. Насколько я понимаю, это согласуется с концепцией Onion Architecture, где инфраструктура и зависимый от платформы код находятся за пределами вашей системы, но наличие пустых классов и пустых интерфейсов кажется неправильным?
Чтобы использовать другую реализацию персистентности (скажем, хранилище таблиц Azure), затем новуюCustomerRepository
класс должен быть создан и будет наследоватьAzureTableStorageRepository
, Но это может привести к избыточному коду (несколько CustomerRepositories)? Как бы этот эффект издевался?
Другая реализация (скажем, хранилище таблиц Azure) имеет ограничения на транснациональную поддержку, поэтому класс AzureTableStorageUnitOfWork не будетт работать в этом контексте.
Есть ли другие проблемы с тем, как я это сделал?
(Я взял большую часть моего вдохновения отэта почта)