我们正在将遗留系统移植到 .NET,既是为了清理架构,也是为了利用许多在遗留系统中不容易实现的新可能性。
注意:在提交之前阅读我的帖子时,我注意到我可能在某些地方描述得太快了,即。掩盖了细节。如果有任何不清楚的地方,请发表评论(不是答案),我会尽可能多地补充
遗留系统使用数据库和 100% 自定义编写的 SQL。这导致了宽表(即许多列),因为需要数据的代码只检索工作所需的内容。
作为移植的一部分,除了自定义 SQL 之外,我们还引入了一个我们可以使用的 ORM 层。我们选择的 ORM 是 DevExpress XPO,其中一个特性也给我们带来了一些问题,即当我们为 Employee 表定义 ORM 类时,我们必须为所有列添加属性,否则它不会为我们检索它们。
这也意味着当我们检索一个 Employee 时,我们会得到所有的列,即使我们只需要一些列。
拥有 ORM 的一个好处是我们可以将一些与属性相关的逻辑放入相同的类中,而不必到处复制它。例如,将名字、中间名和姓氏组合成“显示名称”的简单表达式可以放在那里,作为示例。
但是,如果我们在某处编写 SQL 代码,无论是在类似 DAL 的构造中,还是在任何地方,我们都需要复制这个表达式。这感觉不对,看起来像是错误和维护噩梦的秘诀。
但是,由于我们有两个选择:
- ORM,获取所有内容,可以编写一次逻辑
- SQL,获取我们需要的,需要复制逻辑
然后我们想出了一个替代方案。由于 ORM 对象是从字典代码生成的,我们决定也生成一组哑类。这些将具有相同数量的属性,但不会以相同的方式绑定到 ORM。此外,我们为所有对象添加了接口,也生成了,并使 ORM 和 dum 对象都实现了这个接口。
这使我们能够将其中的一些逻辑移出到与接口相关的扩展方法中。由于哑对象携带了足够的信息让我们将它们插入到我们的 SQL 类中,而不是返回 DataTable,我们可以返回一个 List,并提供可用的逻辑,这看起来是可行的。
然而,这导致了另一个问题。如果我想编写一段代码,仅在我需要知道他们是谁(即他们在系统中的标识符)以及他们的姓名(名字、中间名和姓氏)的上下文中显示或处理员工,如果我使用这个愚蠢的对象,编译器无法保证调用我的代码确实提供了所有这些东西。
一种解决方案是让我们让对象知道哪些属性已被赋值,并且尝试读取未赋值的属性会因异常而崩溃。这使我们有机会在运行时发现代码未传递足够信息的合同违约。
这对我们来说也很笨拙。
所以基本上我想要的建议是是否有其他人曾经或正在这种情况下,以及您可以提供的任何提示或建议。
目前,我们不能拆散桌子。由于端口的大小,旧应用程序仍需存在数年,并且 .NET 代码不是 3 年内发布类型的项目,但将在此过程中逐步发布。因此,遗留系统和 .NET 代码都需要使用相同的表。
我们也知道这不是一个理想的解决方案,所以请不要提出“你不应该这样做”这样的建议。我们很清楚这一点:)
我们研究过的一件事是使用“合同”创建一个 XML 文件或类似文件。所以我们可以在这个 XML 文件中加入如下内容:
- 有一个 Employee 类具有这 50 个属性
- 此外,对于程序的各个部分,我们有这 7 种变体
- 此外,我们有这 10 条逻辑,每条都需要属性 X、Y 和 Z(X、Y 和 Z 在这 10 种之间变化)
这可以让我们对这 8 个类(全类 + 7 个较小的变体)进行代码生成,并让生成器检测到变体 #3 的属性 X、Y 和 K 是否存在,然后我可以将代码绑定到逻辑或逻辑需要自动进入此类的接口。这将允许我们拥有许多不同类型的员工类,具有不同程度的属性覆盖,并让生成器自动将此类支持的所有逻辑添加到它。
然后我的代码可以说我需要一个 IEmployeeWithAddressAndPhoneNumbers 类型的员工。
这看起来也很笨重。