具有依赖注入的工作单元

时间:2013-03-16 13:10:22

标签: dependency-injection inversion-of-control ninject repository-pattern unit-of-work

我正在ASP.NET MVC 4中构建一个相对简单的webapp,使用Entity Framework与MS SQL Server进行通信。将来有很多扩展应用程序的空间,因此我的目标是最大化代码中的可重用性和适应性,以便以后节省工作。这个想法是:

  • 工作单元模式,通过仅在每组操作结束时提交更改来保存数据库问题。
  • 使用BaseRepository<T>的通用存储库,因为存储库大部分都是相同的;奇怪的例外可以扩展并添加其他方法。
  • 依赖注入将这些存储库绑定到控制器将使用的IRepository<T>,以便我可以轻松切换数据存储方法等(不仅仅是为了最佳实践;这有可能是发生)。我正在使用Ninject。

我之前从未尝试过这样的事情,所以我一直在读书,我觉得自己已经糊里糊涂了。到目前为止,我有一个IRepository<T>接口,它由BaseRepository<T>实现,它包含一个传递给它的构造函数的DataContext实例。此接口具有添加,更新,删除和各种类型的Get(单个ID,单个谓词,分组谓词,全部)的方法。目前为止唯一不适合此接口的存储库是Users存储库,它添加User Login(string username, string password)以允许登录(其实现处理所有salting,散列,检查等)。

从我读过的内容来看,我现在需要一个包含所有存储库实例的UnitOfWork类。这个工作单元将公开存储库以及SaveChanges()方法。当我想操作数据时,我实例化一个工作单元,访问它上面的存储库(根据需要实例化),然后保存。如果有任何失败,数据库中没有任何变化,因为它不会在最后达到单个保存。这一切都很好。我的问题是,我能找到的所有例子似乎都做了两件事之一:

  • 有些人将数据上下文传递到工作单元,从中检索各种存储库。这通过在我的工作单元中使用我的特定于实体框架的DbContext(或从其继承的类)来否定DI的观点。
  • 有些人调用Get方法来请求一个存储库,这是一个服务定位器模式,至少不受欢迎,如果不是反模式,我想在这里避免使用它。

我是否需要为我的数据源创建一个接口并将其注入工作单元?我找不到任何明确和/或完整的解释文档。

修改

我想我一直在复杂化它;我现在将我的存储库和工作单元折叠成一个 - 我的存储库完全是通用的,所以这只是给了我一些通用方法(添加,删除,更新和几种Get)以及一个SaveChanges方法。这给了我一个工人类接口;然后我可以有一个工厂类来提供它的实例(也是接口)。如果我也有这个工作器实现IDisposable,那么我可以在一个范围的块中使用它。所以现在我的控制器可以这样做:

using (var worker = DataAccess.BeginTransaction())
{
    Product item = worker.Get<Product>(p => p.ID == prodName);
    //stuff...
    worker.SaveChanges();
}

如果在SaveChanges()之前出现问题,那么当它退出范围块并且工作人员被处置时,所有更改都将被丢弃。我可以使用依赖注入为DataAccess字段提供具体的实现,并将其传递给基本控制器构造函数。业务逻辑全部在控制器中并与IQueryable对象一起使用,因此只要它实现DataAccess接口,我就可以为我喜欢的任何东西切换IRepository提供者对象;实体框架没有任何特定的内容。

那么,对此实施的任何想法?这是在正确的轨道上吗?

1 个答案:

答案 0 :(得分:1)

我更喜欢将UnitOfWorkUnitOfWorkFactory注入存储库,这样每次添加新存储库时我都不必费心。 UnitOfWork的责任就是管理交易。

Here就是我的意思。