什么是支持应用程序中自定义字段的设计模式?

Syl*_*ain 71 database-design data-modeling

我们开发商业应用程序.我们的客户要求提供自定义字段支持.例如,他们想要在Customer表单中添加一个字段.

存储字段值的已知设计模式和有关字段的元数据有哪些?

我现在看到这些选项:

选项1:将varchar类型的Field1,Field2,Field3,Field4列添加到我的Customer表中.

选项2:在customer表中添加一个XML类型的列,并将自定义字段的值存储在xml中.

选项3:添加CustomerCustomFieldValue表,其中包含varchar类型的列,并在该列中存储值.该表还有一个CustomerID,一个CustomFieldID.

CustomerID,  CustomFieldID, Value
10001,       1001,          '02/12/2009 8:00 AM'
10001,       1002,          '18.26'
10002,       1001,          '01/12/2009 8:00 AM'
10002,       1002,          '50.26'
Run Code Online (Sandbox Code Playgroud)

CustomFieldID将是另一个名为CustomField的表中的ID,其中包含以下列:CustomFieldID,FieldName,FieldValueTypeID.

选项4:添加CustomerCustomFieldValue表,其中包含每个可能值类型的列,并在右列中存储值.与#3类似,但使用强类型列存储字段值.

CustomerID,  CustomFieldID, DateValue,           StringValue,       NumericValue                 
10001,       1001,          02/12/2009 8:00 AM,  null,              null
10001,       1002,          null,                null,              18.26
10002,       1001,          01/12/2009 8:00 AM,  null,              null
10002,       1002,          null,                null,              50.26
Run Code Online (Sandbox Code Playgroud)

选项5:选项3和4使用特定于单个概念(客户)的表.我们的客户也要求以其他形式提供自定义字段.我们应该有一个系统范围的自定义现场存储系统吗?因此,我们不是拥有多个表,例如CustomerCustomFieldValue,EmployeeCustomFieldValue,InvoiceCustomFieldValue,而是拥有一个名为CustomFieldValue的表?虽然对我来说似乎更优雅,但这不会导致性能瓶颈吗?

你使用过这些方法吗?你成功了吗?你会选择什么方法?你知道我应该考虑的任何其他方法吗?

此外,我的客户希望自定义字段能够引用其他表中的数据.例如,客户可能想要向客户添加"收藏付款方式"字段.付款方式在系统的其他地方定义.这带来了"外键"的主题.我是否应该尝试创建约束以确保存储在自定义字段表中的值是有效值?

谢谢

======================

编辑07-27-2009:

谢谢您的回答.似乎方法列表现在非常全面.我选择了选项2(单个XML列).这是目前最容易实施的.我可能不得不折射更强烈定义的方法,因为我的要求会变得更复杂,并且支持的自定义字段的数量会变得更大.

Eri*_*yen 14

我同意下面的海报,选项3,4或5最有可能是合适的.但是,您建议的每个实现都有其优点和成本.我建议根据您的具体要求选择一个.例如:

  1. 选项1专业人员:快速实施.允许对自定义字段执行数据库操作(搜索,排序.)
    选项1缺点:自定义字段是通用字段,因此没有强类型字段.数据库表效率低,尺寸大,有许多永远无法使用的无关字段.需要预期允许的自定义字段数.
  2. 选项2专业人员:快速实施.灵活,允许任意数量和类型的自定义字段.
    选项2缺点:自定义字段上无法执行DB操作.如果您只需要显示自定义字段,或者仅基于每个客户对数据进行轻微操作,则最好.
  3. 选项3专业人士:既灵活又高效.可以执行数据库操作,但会对数据进行一些标准化以减少浪费的空间.我同意未知(谷歌)的建议,即添加一个可用于指定类型或来源信息的附加列.选项3缺点:开发时间和查询的复杂性略有增加,但这里确实没有太多的缺点.
  4. 选项4与选项3相同,只是您可以在数据库级别操作您键入的数据.将类型信息添加到选项3中的链接表允许您在我们的应用程序级别执行更多操作,但是DB将无法进行比较或排序.3和4之间的选择取决于此要求.
  5. 选项5与3或4相同,但可以更灵活地将解决方案应用于许多不同的表.在这种情况下的成本将是该表的大小将变得更大.如果您要进行许多昂贵的连接操作以进入自定义字段,则此解决方案可能无法很好地扩展.

PS如下所述,术语"设计模式"通常指的是面向对象的编程.您正在寻找数据库设计问题的解决方案,这意味着有关设计模式的大多数建议都不适用.


Spe*_*ort 10

就应用程序代码而言,我不确定.我知道自定义字段从数据库中的EAV模型中受益匪浅.

根据下面的评论,您可以使用此模型犯下的最重要的错误是将外键放入其中.永远不要把像FriendID或TypeID这样的东西放到这个模型中.将此模型与典型的关系模型结合使用,并将外键字段保留在表列中.

第二个重大错误是将数据放在需要与每个元素一起报告的模型中.例如,在此模型中放置类似用户名的内容意味着,只要您想要访问用户并且需要知道他们的用户名,您就会自己致力于最好的加入或2n个查询,其中n是您正在查看的用户数量.当您考虑到每个User元素通常需要Username属性时,很明显这也应保留在表列中.

但是,如果您只是将此模型与自定义用户字段一起使用,那么您可以.我无法想象很多情况下用户会输入关系数据而EAV模型对搜索没有太大的不利影响.

最后,不要尝试从此加入数据并获得漂亮的漂亮记录集.获取原始记录,然后获取实体的记录集.如果你发现自己想要加入表格,你可能会犯第二个错误,如上所述.


Kai*_*tsu 5

如果您使用面向对象的语言进行开发,我们在这里讨论的是自适应对象模型。有很多关于如何用 oo 语言实现它们的文章,但没有太多关于如何设计数据存储端的信息。

在我工作的公司,我们通过使用关系数据库存储AOM数据解决了这个问题。我们有一个中央实体表来展示域中所有不同的“实体”,比如人、网络设备、公司等......我们将实际的“表单字段”存储到输入的数据表中,所以我们有一个表字符串,一个用于日期等。所有数据表都有一个指向实体表的外键。我们还需要表格来呈现类型方面,即某个实体可以具有什么样的属性(表单字段),这些信息用于解释数据表中的数据。

我们解决方案的优点是无需更改代码即可对任何内容进行建模,包括实体之间的引用、多值等。还可以向字段添加业务规则和验证,并且它们可以在所有形式中重复使用。缺点是编程模型不是很容易理解,查询性能会比更典型的数据库设计更差。对于 AOM 来说,关系数据库以外的其他解决方案可能更好、更容易。

为它构建一个具有工作数据存储的良好 AOM 需要大量工作,如果您没有高技能的开发人员,我不会推荐它。也许有一天会出现满足这些需求的操作系统解决方案。

自定义字段之前已经在 SO 中讨论过: