我正在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)以及一个SaveChanges方法。这给了我一个工人类接口;然后我可以有一个工厂类来提供它的实例(也是接口)。如果我也有这个工作器实现IDisposable
,那么我可以在一个范围的块中使用它。所以现在我的控制器可以这样做:
using (var worker = DataAccess.BeginTransaction())
{
Product item = worker.Get<Product>(p => p.ID == prodName);
//stuff...
worker.SaveChanges();
}
如果在SaveChanges()
之前出现问题,那么当它退出范围块并且工作人员被处置时,所有更改都将被丢弃。我可以使用依赖注入为DataAccess
字段提供具体的实现,并将其传递给基本控制器构造函数。业务逻辑全部在控制器中并与IQueryable
对象一起使用,因此只要它实现DataAccess
接口,我就可以为我喜欢的任何东西切换IRepository
提供者对象;实体框架没有任何特定的内容。
那么,对此实施的任何想法?这是在正确的轨道上吗?
答案 0 :(得分:1)
我更喜欢将UnitOfWork
或UnitOfWorkFactory
注入存储库,这样每次添加新存储库时我都不必费心。 UnitOfWork的责任就是管理交易。
Here就是我的意思。