0

我在ASP.NET MVC 4中使用实体框架与MS SQL Server交谈,构建了一个相对简单的web应用程序。今后有很多扩展应用程序的范围,所以我的目标是在代码中重复使用和适应性最大化的模式,以便以后节省工作。这个想法是:依赖注入工作单元

  • 工作单元模式,通过在每组操作结束时仅提交更改来保存数据库问题。
  • 使用BaseRepository<T>的通用存储库,因为存储库将大部分相同;奇怪的异常可以扩展并添加其他方法。
  • 依赖注入结合这些仓库到IRepository<T>该控制器将使用,这样我可以切换数据存储的方法和这样的最小忙乱(不只是对最佳实践;有这种情况发生的一个真正的机会)。我为此使用Ninject。

我从来没有真正尝试过这样从零开始,所以我一直在阅读,我想我已经把自己弄糊涂了。到目前为止,我有一个接口IRepository<T>,它由BaseRepository<T>实现,它包含DataContext的实例,该实例被传递给它的构造函数。此接口具有用于添加,更新,删除和各种类型的获取(单个按ID,单个按谓词,按谓词分组,全部)的方法。唯一不适合此接口的存储库(到目前为止)是Users存储库,它添加User Login(string username, string password)以允许登录(其实现可处理所有腌制,散列,检查等)。

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

  • 一些传递数据上下文到工作单位,从他们获取各种信息库。这通过在我的工作单元中使用我的实体框架特定的DbContext(或从它继承的类)来否定DI的观点。
  • 一些调用get方法要求的仓库,这是服务定位器模式,这至少是不受欢迎的,如果不是一个反模式,而且无论哪种方式,我想在这里避免它。

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

编辑

我想我被它过于复杂;我现在将我的存储库和工作单元合并为一个 - 我的存储库完全是通用的,因此这只是为我提供了一些通用方法(添加,删除,更新和几种Get)以及一个SaveChanges方法。这给了我一个工人类界面;然后我可以有一个提供它的实例的工厂类(也是接口)。如果我也有这个工人实施IDisposable那么我可以在一个范围内使用它。如果出现错误的SaveChanges()之前,那么当它退出的范围块和职工安置所有的更改将被丢弃

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

:所以现在我的控制器都可以做这样的事情。我可以使用依赖注入来为DataAccess字段提供具体的实现,该字段传递给基础控制器构造函数。业务逻辑全部在控制器中,与IQueryable对象一起工作,因此只要实现IRepository接口,我就可以将DataAccess提供程序对象转换为我喜欢的任何东西;没有任何特定的实体框架在任何地方。

那么,关于这个实现的任何想法?这是正确的轨道?

+0

我很想指出你[YAGNI原则](http://c2.com/cgi/wiki?YouArentGonnaNeedIt)。在学术上追求这个问题没有错,但是我觉得你预见到了很多变化,你可能会看到自己不得不改变你的设计。更糟的是你可能会被卡住。 – 2013-03-16 13:20:41

+0

我明白,通常我会同意,但我知道这可能是需要的。我打算部署到MSSQL服务器的服务器,但我有其他人也想要版本,至少其中一人将无法访问该版本。对于要部署到的所有位置,没有单个系统通用。如果我知道我只需编写一个新的数据访问层实现,并将少量绑定部署到其他地方,它将为我节省工作时间。那我想学习如何正确地做到这一点,这是一个很好的机会。 – anaximander 2013-03-16 13:53:03

+0

完全和你在一起,我对你的设置是什么都没有想法,只是你的描述似乎暗示你正在寻找能够面向未来的东西(我不是那么喜欢的),因此对YAGNI。但是,通过这个澄清,我想你正处在一个可以设计通用的东西的地步。 – 2013-03-16 13:57:51

回答

1

我更喜欢将UnitOfWorkUnitOfWorkFactory注入到存储库中,这样我就不必在每次添加新的存储库时都打扰它。 UnitOfWork的责任只是管理交易。

Here就是我所说的一个例子。