使用DI重构DAL,以后可以更改DAL

本文关键字:DAL DI 重构 使用 | 更新日期: 2023-09-27 17:58:56

我们目前拥有的是一个相对较旧的代码库,它使用EntitySpaces(其实并不重要,但它是一个ORM,在过去使用它很好,但根据我最近的EntityFramework经验,它不再是直接访问数据库的ORM了)。我现在需要更改当前直接依赖EntitySpaces对象的应用程序的许多部分。这不太好,但现在就是这样。我的总体想法是引入一个层,该层引入中立的、不支持持久性的对象,编写某种存储库接口来获取、更新等对象,并编写一个仍然使用EntitySpaces的(第一个)实现。然后,我可以重构所有当前直接使用EntitySpaces的类和组件。这将使我以后能够更改存储库实现,以使用webservice或EntityFramework。

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

一般来说,我想在某个地方放置一个存储库对象,还是最好为返回(特定)存储库的工厂提供组件?也许我甚至可以将存储库拆分为不同类型对象的不同接口,我想这会产生大约20个ish的接口。

比方说,我有UI组件,它们现在对数据库执行许多操作。如果我重写它们以针对存储库工作,是给这些组件一个存储库对象更好,还是以一种他们甚至不必知道某个地方有存储库的方式重写这个UI组件更好?想象一下,有一个对话框可以让您从数据库中加载Part,对其进行更改并将其发回。这可以被视为某种PartEditor接口,当用户点击更新删除按钮时,可以向其提供回调。

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

我知道这很抽象,可能很难回答,但我希望其他人对这类任务有一些经验。我感谢你的指点。至于使用哪种DI框架的问题,我完全开放。

使用DI重构DAL,以后可以更改DAL

一般来说,我想在某个地方放置一个存储库对象,还是最好为返回(特定)存储库的工厂提供组件?也许我甚至可以将存储库拆分为不同类型对象的不同接口,我想这会产生大约20个ish的接口。

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

比方说,我有UI组件,它们现在对数据库执行许多操作。如果我重写它们以针对存储库工作,是给这些组件一个存储库对象更好,还是以一种他们甚至不必知道某个地方有存储库的方式重写这个UI组件更好?想象一下,有一个对话框可以让您从数据库中加载零件,对其进行更改并将其发回。这可以被视为某种PartEditor界面,当用户点击"更新"或"删除"按钮时,它可以被回调使用。

为此,您应该使用存储库模式。您可以在批处理方法的存储库中切换到DataAdapter(如果您已经测量到EF性能对于这些场景来说太差)。这就是抽象的伟大之处。您可以根据需要调整实现,而不会影响代码的其余部分。

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

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

你可以在这里阅读我为EF制作的一个实现:http://blog.gauffin.org/2013/01/repository-pattern-done-right/

一般来说,我是否希望有一个存储库对象在某个地方,还是最好提供一家工厂返回(特定)存储库?也许我甚至可以分开不同类型的对象的不同界面中的存储库,我想这将导致大约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不应该知道存储库。它应该是业务域,像UI和存储库这样的中介

你甚至会使用DI框架来完成这项任务吗?应用程序是相对较大,我认为大约有80万loc,没有在全公司范围内重复使用图书馆。另一种选择是隐藏具体的类来自所有组件,而不使用DI框架,以避免引入新问题。对于使用我的新抽象的组件这不应该有什么不同,因为这些组件应该以一种他们不需要知道所使用的DI框架的方式编写,对吧

是的,使用DI/IoC框架。不要避免不可避免的事情,也不要重新发明轮子——这是一个比使用第三方库更大的问题——!我想向您推荐Castle Windsor,因为它的成熟度、健壮性和功能丰富的框架。