我正在遗留数据库(我无法更改)之上构建一个应用程序。我使用 Linq to SQL 进行数据访问,这意味着每个表都有一个 (Linq to SQL) 类。

我的域模型与数据库不匹配。例如,有两个表,名称为 UsersEmployees, ,因此我有两个名为的 Linq to SQL 类 UserEmployee. 。但在我的领域模型中我希望有一个 User 类应该包含来自任一表的一些字段(但我不关心这些表的许多其他字段)。

我不确定应该如何设计我的存储库:

  • 存储库是否应该执行 Linq 到 SQL 类之间的映射(例如 User, Employee)到域类(User)并且仅将域类返回给应用程序
  • 或者我的存储库应该将 Linq 返回到 SQL 类并将映射留给调用者

第一种方法对我来说似乎更有意义,但是这是实现我的存储库的正确方法吗?

有帮助吗?

解决方案

纯粹主义者(我试图保持纯粹)会告诉你,你的模型代表你的数据。因此,任何需要持久化的事情只有在需要时才通过存储库完成。此外,当您有复杂的实体时,您希望使用服务来组合它们。例如,User + Employee = UserEmployee 实体只能通过 IUserEmployeeService 访问。

有了这些模糊的陈述,你在这里就有了一个绝佳的机会。

构建一个反腐败层,它允许您同时开始摆脱旧数据库。

这是 DDD 手册中的另一章。反腐败层用于使用外观、转换器和适配器与遗留系统进行交互,以将遗留数据库与纯域模型隔离。

现在,这可能比您想要的要多得多。所以,此时你必须问自己:

我想开始摆脱遗产数据库的过程,还是在应用程序的寿命中仍然存在?

如果您的答案是可以开始迁移,则按照您想要的方式对实际域进行建模。将其与普通存储库和服务一起保留。按照您想要的存储方式设计它,享受乐趣。然后,使用聚合根的服务进入反腐败层并提取实体,在本地存储/更新它们,并转换为您域的实体。

如果答案是遗留数据库将在项目的整个生命周期中保留,那么您的任务就会容易得多。使用您域的服务(例如UserEmployeeService)深入到反腐败的UserFacade和EmployeeFacade(类似于“远程服务”概念)。

在 Facades 中,使用适配器访问旧数据库(例如LegacyDbSqlDatabase)来获取原始的legacyUser()。下一步是使用 UserTranslator() 和 EmployeeTranslator() 映射器将遗留用户数据转换为您实际域的 User() 实体版本,并将其从 UserFacade 返回到您的 UserEmployeeService,并在其中与来自同一个地方的 Employee 实体。

哎哟,打了好多字啊……

使用反腐败层的适配器和外观,您可以执行 Linq-to-Sql 或任何您想做的事情。这并不重要,因为您已经将遗留数据库/系统与您美好而纯粹的域完全隔离开来 - 您的域拥有自己版本的 User() 和 Employee() 实体和值对象。

其他提示

DDD 和 Linq To SQL 不能很好地结合在一起,因为生成的类不会显着偏离数据库表结构。您必须以一种使使用 Linq to SQL 变得很痛苦的方式映射您的类,或者只能接受不理想的对象模型。

如果您确实想利用 DDD 和存储库模式,请选择 Entity Framework 甚至更好的 NHibernate。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top