使用DI重构DAL,以后能够更改DAL

时间:2013-02-12 10:01:26

标签: c# .net architecture dependency-injection refactoring

我们目前拥有的是一个相对较旧的代码库,使用EntitySpaces(并不重要,但它是一个ORM,这在当时很好用,但我最近的EntityFramework经验并非如此很多)作为ORM直接访问数据库。我现在面临着需要更改当前直接依赖于EntitySpaces对象的许多应用程序。这不好,但现在就是这样。 我的一般想法是引入一个层,它引入中性,持久性 - 不知道的对象,编写某种存储库接口来获取,更新等对象并编写仍然使用EntitySpaces的(第一个)实现。然后我可以重构当前直接使用EntitySpaces的所有类和组件。这有望使我能够在以后更改存储库实现以使用Web服务或EntityFramework。

以下是我的问题/不安全感:

通常,我是想让一个存储库对象位于某个地方,还是更好地为组件提供返回(特定)存储库的工厂?也许我甚至可以在不同类型的对象的不同接口中拆分存储库,这会产生一些20-ish接口。

假设我有UI组件,现在它们对数据库执行大量操作。如果我重写它们以对抗存储库,那么最好“给”这些组件一个存储库对象,或者以一种他们甚至不知道某处存在存储库的方式重写这些UI组件?想象一下有一个对话框,允许您从数据库加载Part,更改它并将其发回。这可以被视为某种PartEditor接口,当用户点击 Update Delete 按钮时,可以使用回调来使用。

你甚至可以使用DI框架来完成这项任务吗?该应用程序相对较大,我认为大约800k左右,没有重用公司范围的库。另一种方法是在不使用DI框架的情况下隐藏所有组件的具体类,以避免引入新问题。对于使用我的新抽象的组件,这应该没有区别,因为这些组件应该以他们不需要知道所使用的DI框架的方式编写,对吗?

我知道这很抽象,也许很难回答,但我希望其他人对这类任务有一些经验。我感谢任何指针。至于哪个DI框架使用的问题,即时完全开放。

2 个答案:

答案 0 :(得分:2)

  

通常,我是想让一个存储库对象位于某个地方,还是更好地为组件提供返回(特定)存储库的工厂?也许我甚至可以在不同类型的对象的不同接口中拆分存储库,这会产生一些20-ish接口。

我会为每个聚合根创建一个存储库。这样可以更轻松地维护和测试代码。

  

假设我有UI组件,现在它们对数据库执行大量操作。如果我重写它们以对抗存储库,那么最好“给”这些组件一个存储库对象,或者以一种他们甚至不知道某处存在存储库的方式重写这些UI组件?想象一下,有一个对话框,允许您从数据库加载零件,更改它并将其发回。这可以看作是某种PartEditor接口,当用户点击Update或Delete按钮时,它可以被赋予回调。

您应该使用存储库模式。您可以切换到存储库中的DataAdapter以进行批处理方法(如果您已经确定EF性能对于那些有些不同的人来说太差了)。这就是抽象的好处。您可以根据需要调整实现,而不会影响其余代码。

  

你甚至可以使用DI框架来完成这项任务吗?该应用程序相对较大,我认为大约800k左右,没有重用公司范围的库。另一种方法是在不使用DI框架的情况下隐藏所有组件的具体类,以避免引入新问题。对于使用我的新抽象的组件,这应该没有区别,因为这些组件应该以他们不需要知道所使用的DI框架的方式编写,对吗?

在使用数据库时,我确实使用了DI框架。它使得所有存储库共享相同的连接和事务(不升级到分布式事务)变得容易得多。

您可以在此处阅读我为EF所做的实施:http://blog.gauffin.org/2013/01/repository-pattern-done-right/

答案 1 :(得分:1)

  

一般来说,我是否想要一个存储库对象   在哪里或者更好地为组件提供工厂   返回(特定)存储库?也许我甚至可以拆分   存储库在不同类型的对象的不同接口中,   这会产生一些20-ish接口。

我建议您创建一个隐藏域到数据转换的通用存储库(使用OR / M或其他),然后使用控制反转实例化它:

// The factory hides who's the actual 
// repository implementation. In your case, it could be 
// EntityFrameworkRepository<T> or EFGenericRepository<T>
GenericRepository<Order> orderRepo = RepositoryFactory.Create<Order>();

存储库可能有以下方法:

  • 添加。
  • GetById。
  • 删除。
  • GetByCriteria([表达式树])(例如,queryable => queryable.Where(...))。此方法可以接受输入参数Expression<Func<IQueryable<T>, IQueryable<T>>>。实体框架和NHibernate将允许您以这种方式实现它。

使用这种方法 - 通用存储库 - 您可以避免使用20,30个存储库,此外,您还有一个实现OR / M特定任务的基本存储库实现,以避免在您的代码库中传播特定的依赖项!

  

让我们说我有UI组件,现在可以执行大量操作   数据库。如果我重写它们来对抗存储库就可以了   最好“给”这些组件一个存储库对象或重写   这个UI组件以他们甚至不必知道的方式存在   存储库在哪里?想象一下有一个对话框可以让你加载一个   部分来自数据库,更改它并将其发回。这可以看出来   作为某种PartEditor接口,可以给出   当用户点击“更新”或“删除”按钮时使用的回调。

用户界面不应该知道存储库。它应该是业务领域的UI和存储库之类的中介。

  

你甚至可以使用DI框架来完成这项任务吗?申请是   相对较大,我认为大约有800k左右,没有在公司范围内重复使用   库。另一种方法是隐藏具体的类   来自所有组件而不使用DI框架,以避免   引入新问题。对于使用我的新抽象的组件   这不应该有所作为,因为这些组件应该是   以他们不需要知道所使用的DI框架的方式编写,   正确?

是的,使用DI / IoC框架。不要避免不可避免的,不要重新发明轮子 - 这是一个比使用第三方图书馆的主要问题 - !我想建议你Castle Windsor因为它的成熟度,健壮性和功能丰富的框架。