具有UnitOfWork和Repository模式的DI

时间:2014-04-26 20:47:38

标签: c# asp.net-mvc dependency-injection repository simple-injector

作为一个学习过程,我尝试使用存储库模式实现UoW,并且我有以下设置:

public interface IUnitOfWork : IDisposable
{
  MyEntities Context { get; set; }

  string GetConnectionString()
  void Complete();
}

public abstract class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
  protected MyEntities context;

  protected DbSet<TEntity> dbSet;

  protected RepositoryBase(IUnitOfWork unitOfWork)
  {
     context = unitOfWork.Context;
     dbSet = context.Set<TEntity>();
  }
}

public class ItemRepository : RepositoryBase<Item>, IItemRepository
{
  public ItemRepository(IUnitOfWork unitOfWork)
     : base(unitOfWork)
  {
  }

  public Item GetById(int id)
  {
     // return a item
  }
 }

要实际使用ItemRespoitory,我正在执行以下操作:

using (var unitOfWork = new UnitOfWork())
{
    var ItemRepository = new ItemRepository(unitOfWork);

    var item = ItemRepository.GetById(1);
}

工作正常,现在我想用IoC / DI和简单的进样器做到这一点:

var container = new Container();

container.Register<IUnitOfWork, UnitOfWork>();
container.Register<IItemRepository, ItemRepository>();

container.Verify();

DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

但现在我的问题是,因为我正在将ItemRepository注入控制器的构造函数

public MyController(IItemRepository itemRepository)
{
   _itemRepository = itemRepository;
}

当我完成存储库后,我应该如何处理工作单元?因为我没有必要 创建一个单元工作并将其包装在using语句中。我这样做了吗?在我的案例中,应用DI与UoW和repo模式的正确方法应该是什么?感谢。

2 个答案:

答案 0 :(得分:2)

您需要将数据服务注册为每个请求 - 对于上面的示例,它可以是Per Web RequestPer Web Api Request

在nuget上查找并安装SimpleInjector.Integration.Web,然后更改:

 container.Register<IUnitOfWork, UnitOfWork>();
 container.Register<IItemRepository, ItemRepository>();

到此(假设MVC):

 container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
 container.RegisterPerWebRequest<IItemRepository, ItemRepository>();

你已经完成了。

答案 1 :(得分:0)

如果您将工作单元(UoW)与存储库结合使用,更好的方法是设置UoW以将存储库作为属性保存,而不是将Uow注入每个存储库。

示例:

工作单位(界面):

public interface IUnitOfWork
{
    void Commit();
    IRepository<Store> Stores { get; }
    IRepository<Product> Products { get; }
}

存储库(接口):

public interface IRepository<T> where T : class
{
    IQueryable<T> GetAll();
    T GetById(Guid id);
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
    void Delete(Guid id);
}

现在你的控制器中你会有:

public class ProductsController: Controller
{

    protected IUnitOfWork Uow { get; set; }

    public ProductsController(IUnitOfWork uow)
    {
        if (uow == null)
            throw new ArgumentNullException("Unit of Work");

        Uow = uow;
    }


}

然后像这样设置你的IoC:

public static void RegisterIoc(HttpConfiguration config)
{
     var container = new Container();

     container.Register<IUnitOfWork, UnitOfWork>();
     container.Register<IRepository<Store>, Repository<Store>>();
     container.Register<IRepository<Product>, Repository<Product>>();

}

现在,当您需要Product DbContext时,您可以访问控制器中注入的单个Uow。另请注意Commit方法,这意味着您的实施中只有_dbContext.SaveChanges()次调用。这就是工作单元的全部内容,对DbContext进行一些更新调用并进入数据库一次。所以,你有一个像setup这样的事务(意思是,如果出现问题在代码中,任何东西都不会在数据库中更新)。

请注意,这不是一个完全有效的示例,但它应该让您了解如何进行设置。如果您需要有关如何使其工作的教程,您可以查看John Papa关于PluralSight的Single Page Application课程(这是该代码所基于的)。但他有一个非常复杂的设置(虽然非常灵活),这可能有点多开始。