将属性存储为(名称-值-对)表

本文关键字:名称 属性 存储 | 更新日期: 2023-09-27 18:30:37

我想编写一个应用程序如下:

SQL 表的名称是:(部门属性)

+----+-------+----------+------------------------+------------+
| Id | DepId |   Type   |          Name          |   Value    |
+----+-------+----------+------------------------+------------+
|  2 |   123 | String   | DepartmentDescription  | xxxx       |
|  3 |   123 | DateTime | DateCreated            | xx/xx/xxxx |
|  4 |   321 | String   | DepartmentDescription  | xxxx       |
|  5 |   321 | Boolean  | NewerDep               | xx/xx/xxxx |
+----+-------+----------+------------------------+------------+

并通过 [DepId] 获取所有值

select * from DepProperties where DepId = 123

并且,在 VB.Net 序列化为类

Public Class Department
    Public Property DepartmentDescription As String
    Public Property DateCreated As DateTime
End Class
Public Class ExtendedDepartment
    Inherits Department
    Public Property NewerDep As Boolean
End Class

我尝试使用这种方式。

因为将来当我向特定部门添加新属性时仅从父类扩展的新类包含特定属性

而不是在数据库中添加新列。

这是一个好方法,它怎么能做到这一点?

将属性存储为(名称-值-对)表

您提出的通常被称为实体-属性-值设计(或简称 EAV),正如@DanGuzman在他的评论中指出的那样,根据许多因素,它可能会成为性能问题,包括:

  • 表中的行数
  • 同时使用该表的并发连接数
  • 客户端代码是如何编写的;即它是否使用此模式来存储其所有数据,或者这仅适用于有限数量的属性?
有很多

商业系统完全基于这样的设计构建,它们确实支持大量的并发性,具有大量行和精心设计的客户端代码。

来自维基百科关于EAV1的文章:

如上所述,使用 EAV 模型的典型情况是高度稀疏的异质属性,例如电子病历 (EMR) 中的临床参数。然而,即使在这里,准确地说EAV建模原则应用于数据库的子模式,而不是其所有内容。(例如,患者人口统计数据最自然地以每个属性一列的传统关系结构建模。

因此,关于EAV

与"关系"设计的争论反映了对问题的不完全理解:EAV设计应该只用于需要对稀疏属性进行建模的数据库的子模式:即使在这里,它们也需要由第三个范式元数据表支持。遇到稀疏属性的数据库设计问题相对较少:这就是为什么EAV设计适用的情况相对较少的原因。即使在遇到稀疏数据的情况下,一组 EAV 表也不是解决稀疏数据的唯一方法:当每个实体的最大属性数相对适中且稀疏数据总量也同样适中时,基于 XML 的解决方案(如下所述)适用。这种情况的一个示例是捕获不同产品类型的变量属性的问题。

稀疏属性也可能发生在电子商务情况下,其中组织正在购买或销售大量高度多样化的商品,其中各个商品类别的详细信息变化很大。

您可能需要考虑使用下表设计:

CREATE TABLE dbo.DepProperties
(
    DepPropertiesID INT NOT NULL
        CONSTRAINT PK_DepProperties
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , DepId INT NOT NULL
    , PropertyType VARCHAR(50) NOT NULL
    , PropertyName VARCHAR(50) NOT NULL
    , PropertyValueString VARCHAR(247) NULL /* Adjust this number to
                                               allow for the largest
                                               value you want to 
                                               support */
    , PropertyValueInt INT NULL
    , PropertyValueDate DATE NULL
    , PropertyValueDateTime DATETIME NULL
    , PropertyValueDecimal DECIMAL(20, 10) /* Adjust per your needs */
);

请注意,"值"列可为空,每种类型的数据都有离散列。 这允许您保留类型安全性。


1 - https://en.wikipedia.org/wiki/Entity-attribute-value_model#Modeling_sparse_attributes