使用XML字段Vs.为不稳定的组织创建一个表

时间:2012-02-05 08:40:29

标签: entity-framework database-design linq-to-xml data-access-layer

我正在设计一个应用程序来发布和存储组织的发票。问题是组织根本不稳定。有很多类型的发票,它们可能会增加和改变。

首先,我尝试在DAL中使用表格,一个表格用于存储发票,一个用于发票字段,一个用于发票字段值。问题是,这种方式需要Reflection稍后检测字段,这可能会在发票包含大量项目时减慢应用程序。

其次,我尝试将发票数据核心保存为两个表:发票和发票项目。其他字段可以从其他表中完全捕获。我的意思是,业务层应该为每种发票类型提供不同的结果。它应该选择正确的查询,并根据发票类型处理结果。该解决方案存在两个问题:

  1. 当我想要显示时,我仍然在其他表之间有很多连接 每张发票项目的发票。我应该重新计算一切 每次发票项目。

  2. 如果发票项目表不支持新类型,该怎么办? 发票?然后我可能应该添加一个新表来存储那种发票项目。

  3. 我的客户要求我保留与发票相关的所有数据,他们这样做 不想让我每次都重新计算它。他们想要的东西像 发票创建时相关数据的快照。

  4. 现在,我认为我可以在表中使用XML的好处吗?我可以将发票保存为xml。

    • 我可以保存不同版本的发票。
    • 在更改时,我只更新了我的Business.dll,并且不需要更改DAL。
    • Linq to XML并不慢。

    你有什么建议?

2 个答案:

答案 0 :(得分:4)

我们已经使用这种方法已有几年了,但与nhibernate结合使用。 它的工作非常适合网上商店,你必须修改数据层。但是您可以使用新的模型定义创建自定义项目(IoContainer通常有助于解决依赖关系)。

非常适合将重要数据分解到单独的列中,而将其余的动态内容分解到一个XML列中。所有查询都必须仅适用于表列(以获得最佳性能)。为了获得休息数据,我们有一个实体基类,它在后台序列化和反序列化数据到其余的“虚拟”字段。

为了进一步提高应用程序性能,我们使用内部搜索器/抓取工具,它比与数据库的通信更快地返回数据。

因为nhibernate不支持(本机)linq - 现在我正在为实体框架寻找替代的,已经实现的变体。

如果有人要分享信息 - 请看,并且好看。检查(并与我们的变体进行比较 - 选择更好的一个)......

答案 1 :(得分:2)

发票系统通常需要拍摄发票及其所有关系的快照。原因是公司的变化。例如:

  1. 如果产品价格发生变化,则不得影响已处理的发票
  2. 如果产品停产,则不得影响已处理的发票
  3. 如果客户更改其地址,则不得影响已处理的发票
  4. 发票始终必须显示从创建发票之日起的系统状态数据。您可以通过发票和发票项目表的某种程度的非规范化或大量与发票相关的记录来实现这一目标。

      

    现在,我认为我可以在表中使用XML的好处吗?我可以将发票保存为xml。

    是的,你可以但是对于实体框架,这个字段只是一个字符串,因为它不了解SQL XML数据类型。

      

    Linq to XML并不慢。

    Linq-to-XML并不重要,因为Linq-to-XML是用于查询加载的XML文档的.NET功能。除非您将SQL服务器中的所有发票加载到应用程序并在应用程序的内存中进行Linq-to-XML查询,否则它将查询存储在SQL Server中的XML文档。这很慢,实际上这是你的应用程序的杀手。

    要在SQL Server中查询XML数据,必须使用具有XML功能的本机SQL(XPath,XQuery)。对于SQL人员来说,问题是XML和查询XML将如何影响查询的整体性能以及它对您的需求的满足程度。

      

    在更改时,我只更新我的Business.dll并且不需要更改DAL。

    几乎没有。您还必须更新DAL,因为查询XML的所有SQL查询都将放在那里。除非您有一些非常复杂的数据结构来配置新发票类型的应用程序(包括完整的UI配置,因为新字段可以有新的规则和验证,它可以是从其他数据源填充的组合框等),您将不得不也更新了用户界面。

    你有什么选择?

    • 使用XML并删除EF
    • 使用EF并构建应用程序,以便每次创建新的发票类型时,您都必须向DAL,BLL和UI添加一小段代码以支持它。例如,可以定义标准,应用程序必须以允许在5-10 MD内添加新发票类型的方式进行架构。我在处理订单的反向应用程序中使用了这种方式(但最后我们发现在允许的时间内无法满足业务需求,因为每个新的订单类型都包含许多新的要求,包括与新的外部数据源集成它需要单独的项目发布。)
    • 将EF与虚拟扩展性结合使用。每个发票和发票行项目都将包含X个附加字段(您可以为它们使用不同的类型或只使用字符串 - 这取决于您的期望)。这些字段将用于自定义。您还需要一些配置表,这些配置表将说明哪些发票类型使用哪些字段,这些字段的验证是什么以及这些字段的UI名称和顺序是什么。我看到这个系统成功用于发票中的5个字符串字段和发票行中的5个字符串字段。
    • 将EF和固定表用于仅包含所有发票类型之间共享数据的发票和发票行。使用其他表来包含其他字段和配置表以描述字段类型。在您的应用程序中,不要使用反射,而是使用其他字段,如字典(键,值集合)。对于简单的可扩展性,这是非常常见的结构。

    以前的案例都不能解决新发票类型可能遇到的所有问题。例如,如果新字段是对其他字段的某种关系依赖性,高级业务验证或需要一些外部数据,则实际上将无法解决。

    完全通用的系统可以接受他们创造的任何类型的发票,但该系统的复杂性和价格将至少高出10倍。它还会影响交付应用程序的时间。复杂性也会对可用性产生影响,因为应用程序需要非常谨慎的用户体验设计才能使用。

    这是项目管理中的典型故障,其中需求的价格未正确传达,因此项目的期望远远大于预算允许的期望。同时开发业务项目并没有优化业务流程,只是跟随混乱,这是一场噩梦。

    我看到了一些项目,期望现在有一个应用程序可以服务(没有任何额外的开发)所有可能的未来案例,而不知道如何定义这些案例。当然预算总是足以提供目前已知的案例。所有这些项目均未达到此要求。

    顺便说一下。为确保您尽可能多地处理案件,您不应该从一开始就使用所有当前的发票类型。只需让您的分析师为每种发票类型收集最少的字段集并使用它们。必须通过系统配置所有实际发票类型,而不是硬编码。