【问题标题】:Need advice on combining ORM and SQL with legacy system需要有关将 ORM 和 SQL 与遗留系统结合的建议
【发布时间】:2010-09-22 13:42:00
【问题描述】:

我们正在将旧系统移植到 .NET,既是为了清理架构,也是为了利用许多在旧系统中不容易实现的新可能性。

注意:在提交之前阅读我的帖子时,我注意到我可能在某些地方描述得太快了,即。掩盖了细节。如果有任何不清楚的地方,请发表评论(不是答案),我会尽可能地补充

遗留系统使用数据库,并且到处都是 100% 自定义编写的 SQL。这导致了宽表(即许多列),因为需要数据的代码只检索工作所需的内容。

作为移植的一部分,除了自定义 SQL 之外,我们还引入了一个我们可以使用的 ORM 层。我们选择的 ORM 是 DevExpress XPO,其中一个特性也给我们带来了一些问题,即当我们为 Employee 表定义 ORM 类时,我们必须为所有列添加属性,否则它不会为我们检索它们。

这也意味着当我们检索一个 Employee 时,我们会得到所有的列,即使我们只需要一些列。

拥有 ORM 的一个好处是我们可以将一些与属性相关的逻辑放入相同的类中,而不必到处复制它。例如,将名字、中间名和姓氏组合成“显示名称”的简单表达式可以放在此处,作为示例。

但是,如果我们在某处编写 SQL 代码,无论是在类似 DAL 的构造中,还是在任何地方,我们都需要复制此表达式。这感觉不对,看起来就像是错误和维护噩梦的秘诀。

但是,既然我们有两个选择:

  • ORM,获取所有内容,可以编写一次逻辑
  • SQL,获取我们需要的,需要复制逻辑

然后我们想出了一个替代方案。由于 ORM 对象是从字典代码生成的,我们决定也生成一组哑类。这些将具有相同数量的属性,但不会以相同的方式绑定到 ORM。此外,我们为所有对象添加了接口,也生成了,并使 ORM 和虚拟对象都实现了这个接口。

这使我们能够将其中的一些逻辑移出到与接口相关的扩展方法中。由于哑对象携带了足够的信息让我们将它们插入到我们的 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 类型的员工。

这看起来也很笨重。

【问题讨论】:

    标签: c# sql orm interface business-objects


    【解决方案1】:

    我建议最终可能需要进行数据库重构(规范化)。您可以进行重构并使用视图为遗留应用程序提供与数据库一致的接口,使其与预期一致。也就是说,例如,将employee 表分解为employee_info、employee_contact_info、employee_assignments,然后为遗留应用程序提供一个名为employee 的视图,该视图在这三个表之间进行连接(或者如果逻辑是基于表的函数,则可能是更复杂)。这有可能让您继续使用完全基于 ORM 的解决方案,这是我更喜欢的解决方案,并让您的遗留应用程序满意。我不会继续使用 ORM/直接 SQL 的混合解决方案,尽管您可以通过拥有一些提供相同数据的不同视图的实体类来增强您的 ORM(例如连接几个表以进行只读显示)。

    【讨论】:

      【解决方案2】:

      “我们目前无法拆分表格。由于端口的大小,遗留应用程序仍将存在数年,并且 .NET 代码不是 in-3 -years-release 类型的项目,但将在发布过程中分阶段进行。因此,遗留系统和 .NET 代码都需要使用相同的表。"

      两个词:物化视图。

      您有几种“就地标准化”的方法。

      1. 物化视图,a/k/a 索引视图。这是源表的标准化克隆。

      2. 从旧表显式复制到新表。 “我”你说。但是,请考虑您将逐步从旧应用程序中删除功能。这意味着您将在新的规范化表中拥有一些功能,并且可以优雅地忽略旧表。

      3. 显式 2 路同步。这很难,并非不可能。您通过从旧表复制到正确设计的表进行规范化。作为临时解决方案,您可以使用存储过程和触发器将事务克隆到遗留表中。然后,随着转换的进行,您可以淘汰这些杂物。

      在两个完全不同的模式中执行此操作会很高兴。由于旧数据库可能没有精心设计的架构,因此您的新数据库将拥有一个或多个命名架构,以便您可以对定义进行一些版本控制。

      【讨论】:

        【解决方案3】:

        虽然我没有使用过这种特殊的 ORM,但在某些情况下,视图在为这些类型的数据库中的显示和报告提供更轻量级的对象时很有用。根据他们的文档,他们确实支持这样的概念:XPView Concepts

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-02-03
          • 2020-12-27
          • 2011-07-10
          • 1970-01-01
          • 1970-01-01
          • 2021-06-14
          • 2012-12-09
          相关资源
          最近更新 更多