这是我第一次实施更受领域驱动的设计方法。我决定尝试洋葱架构,因为它专注于域而不是基础设施/平台/等。
为了从实体框架中抽象出来,我创建了一个具有工作单元实现的通用存储库。
和IRepository<T>
接口IUnitOfWork
:
public interface IRepository<T>
{
void Add(T item);
void Remove(T item);
IQueryable<T> Query();
}
public interface IUnitOfWork : IDisposable
{
void SaveChanges();
}
IRepository<T>
和的实体框架实现IUnitOfWork
:
public class EntityFrameworkRepository<T> : IRepository<T> where T : class
{
private readonly DbSet<T> dbSet;
public EntityFrameworkRepository(IUnitOfWork unitOfWork)
{
var entityFrameworkUnitOfWork = unitOfWork as EntityFrameworkUnitOfWork;
if (entityFrameworkUnitOfWork == null)
{
throw new ArgumentOutOfRangeException("Must be of type EntityFrameworkUnitOfWork");
}
dbSet = entityFrameworkUnitOfWork.GetDbSet<T>();
}
public void Add(T item)
{
dbSet.Add(item);
}
public void Remove(T item)
{
dbSet.Remove(item);
}
public IQueryable<T> Query()
{
return dbSet;
}
}
public class EntityFrameworkUnitOfWork : IUnitOfWork
{
private readonly DbContext context;
public EntityFrameworkUnitOfWork()
{
this.context = new CustomerContext();;
}
internal DbSet<T> GetDbSet<T>()
where T : class
{
return context.Set<T>();
}
public void SaveChanges()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
客户存储库:
public interface ICustomerRepository : IRepository<Customer>
{
}
public class CustomerRepository : EntityFrameworkRepository<Customer>, 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<IUnitOfWork>();
var customerRepository = container.Resolve<ICustomerRepository>();
return View(customerRepository.Query());
}
[HttpPost]
public ActionResult Create(Customer customer)
{
var unitOfWork = container.Resolve<IUnitOfWork>();
var customerRepository = container.Resolve<ICustomerRepository>();;
customerRepository.Add(customer);
unitOfWork.SaveChanges();
return RedirectToAction("List");
}
}
统一的依赖注入:
container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>();
container.RegisterType<ICustomerRepository, CustomerRepository>();
解决方案:
问题?
存储库实现(EF 代码)非常通用。这一切都在
EntityFrameworkRepository<T>
课堂上。具体模型存储库不包含任何此类逻辑。这使我免于编写大量冗余代码,但可能会牺牲灵活性?ICustomerRepository
和CustomerRepository
类基本上是空的。它们纯粹是为了提供抽象。据我了解,这符合 Onion 架构的愿景,在这种架构中,基础设施和平台相关代码位于系统外部,但空类和空接口感觉不对?要使用不同的持久性实现(例如 Azure 表存储),则
CustomerRepository
需要创建一个新类并继承一个AzureTableStorageRepository<T>
. 但这可能会导致冗余代码(多个 CustomerRepositories)?这将如何影响嘲笑?另一种实现(例如 Azure 表存储)对跨国支持有限制,因此 AzureTableStorageUnitOfWork 类在这种情况下不起作用。
我这样做的方式还有其他问题吗?
(我的大部分灵感来自这篇文章)