【问题标题】:Custom Fields for a Form representing an object表示对象的表单的自定义字段
【发布时间】:2011-11-16 02:57:37
【问题描述】:

我有一个关于对象视图中的自定义字段的架构问题。假设您有一个用户对象,其中包含一些基本信息,例如所有客户都可以使用的名字、姓氏……。

现在,我们经常会收到客户提出的添加几个针对其域的典型自定义字段的问题。我们现在的解决方案是存储键值对的 xml 数据列。到目前为止一切正常,但现在我们必须找到一个更具架构性的解决方案。

例如,现在客户想要一个下拉菜单,可以在其中选择自定义字段的值。我们仍然可以将选定的值存储在 xml 数据列中,但是我们将所有这些下拉值存储在哪里...

我知道在 sharepoint 中您还可以添加自定义字段,例如下拉菜单,我想知道如何最好地处理这个问题。我想避免为客户创建自定义表格,或者有一个包含 90 列的表格(10 个基本列,然后每个客户 10 个列),...

你明白了,它应该是通用的,并且能够处理未来的各种问题。

我在想的是一个表 UserConfiguration,其中每条记录都有一个指向客户的外键(我们数据库中的通道),然后是一个字段名列、一个字段类型列和一个值列。列值应该是 xml 类型的列,因为对于下拉列表,我们需要添加多个值。此外,每个值都可以附加额外的数据(不仅仅是名称)。另一个问题是如何存储选定的值。我不喜欢在我的数据库中有外键到 xml 的想法(在 Azure 无法很好地处理这一切的地方阅读)。您是否只存储值的名称(如果该值从 xml 中消失怎么办?)?

关于这类问题的任何文档、链接也很好。我正在尝试在数据库中找到一种处理此类问题的设计模式。

【问题讨论】:

  • 如果这是题外话,那么你就不是现实生活中的程序员。
  • 你在 SO:stackoverflow.com/questions/1126783/… 上看到过这个吗?这个主题似乎很全面。
  • @Simon Thx,还没找到。

标签: database forms sharepoint design-patterns architecture


【解决方案1】:

这实际上更像是一个评论而不是一个答案,但我需要比 SO 允许 cmets 更多的空间,所以这里是:

我认为您的 UserConfiguration 表方法很好,并且建议您只对设计的“类型”和“值”部分进行更多抽象:

  • 由于您的应用程序需要验证用户输入,“类型”的每个概念都将有一个关联的评估逻辑。显然,您可以将其抽象为数据的越多,就越容易使您的代码保持较小。枚举列表是一个好的开始,但是如果您的“验证器”逻辑可以扩展为处理文本字符串和布尔逻辑表达式的模式匹配(例如,描述/强制输入值的约束),那么您几乎可以表达任何“类型”您的应用程序可能需要处理的输入(相对)简单的“原子”,您可以自然地映射到数据库表。

  • 当存储用户指定的值时,您可以存储“原始”数据(例如 JSON)和关联“类型”的外键,或者您可以添加一个查找/缓存系统来分配系统遇到的每个新值的整数(例如,可以通过检查“原始”数据的散列来检查“新颖性”)。如果您期望有大量数据重复(在多选菜单的情况下当然会出现这种情况),后一种方法显然可以更好地扩展。

【讨论】:

    【解决方案2】:

    我想分两部分回答你的问题:
    1) 在数据库服务器中实现自定义字段
    2) 将自定义字段限制为值的枚举


    尽管@Simon 引用的question 中讨论了 1) 的常见解决方案,但也许您正在寻找一些关于问题是什么以及为什么我们尚未解决问题的讨论。

    • 数据库非常适合结构化、类型化的数据
    • 自定义字段本质上不太结构化
    • 因此,自定义字段更难在数据库中使用
    • 失去了使用数据库的一些或许多优点
      • 有些查询可能更难或不可能
      • 类型安全可能会丢失(在数据库中)
      • 可能不再(由数据库)强制执行数据完整性
      • 实现者和维护者的工作量要大得多

    正如other question 中所述,没有完美的解决方案。
    但是这些好处/功能仍然需要在某个地方实现,因此应用程序通常会负责数据完整性和类型安全。
    对于这样的情况,人们创建了Object-Relation Mapping tools,尽管就像 Jeff Atwood says 一样,即使使用 ORM 也可能会产生比它解决的问题更多的问题。但是,您提到它“应该是通用的,并且能够处理未来的各种问题”——这让我认为 ORM 可能是您最好的选择。

    所以,总结一下我的答案,这是一个已知解决方案的已知问题,没有一个是完全令人满意的(因为它太难了)。选择你的毒药。


    回答您问题的第二部分(我认为是):
    如链接问题中所述,您可以在数据库中为自定义字段实现Entity-Attribute-Value,然后添加一个额外的表来保存每个实体的合法值。那么,EAV 表的属性/值就是属性值表的外键。

    例如,

    CREATE TABLE `attribute_value` ( -- enumerations go in this table
        `attribute` varchar(30), 
        `value` varchar(30), 
        PRIMARY KEY (`attribute`, `value`)
    );
    
    CREATE TABLE `eav` ( -- now the values of attributes are restricted
        `entityid` int, 
        `attribute` varchar(30), 
        `value` varchar(30), 
        PRIMARY KEY (`entityid`, `attribute`), 
        FOREIGN KEY (`attribute`, `value`) REFERENCES `attribute_value`(`attribute`, `value`)
    );
    

    当然,这个解决方案并不完美或不完整——它只是为了说明这个想法。例如,它使用 varchars,并且缺少 type 列。另外,谁来决定每个属性的可能值是什么?用户可以随时更改这些内容吗?

    【讨论】:

      【解决方案3】:

      当您让用户创建数据模型时,我建议您查看文档数据库或“NoSQL”,因为您正是想要这样来存储无模式数据结构。

      此外,sharePoint 以您提到的方式存储元数据(10 列文本,5 列日期等)

      也就是说,在我当前的项目中(锁定在 SharePoint 中,因此 Framework 3.5 + SQL Server 以及随后的所有约束)我们使用类似于以下的结构:

      Form
       Id
      
      Attribute (or Field)
       Name
       Type (enum) Text, List, Dates, Formulas etc
       Hidden (bool)
       Mandatory
       DefaultValue
       Options (for lists)
       Readonly
       Mask (for SSN etc)
       Length (for text fields)
       Order
      
      Metadata
       FormId
       AttributeId
       Text (the value for everything but dates)
       Date (the value for dates)
      

      我们的公式使用诸如 Increment:INC([attribute1][attribute2], 6) 之类的函数,对于表单的属性 1 和属性 2 的组合值的第 999 个实例,这将产生类似 000999 的值,其存储为:

      AttributeIncrementFormula
       AtributeId
       Counter
       Token
      

      诸如条形码之类的其他“公式”(也就是任何重要的东西)都存储为单个元数据值。在实际的实现中,我们会有这样的东西:

      var form = formRepository.GetById(1);
      form.Metadata["firstname"].Value
      

      上面的值是一个只读属性,它决定我们是否应该从 Text 或 Date 中获取值,以及是否需要进行一些额外的转换。请注意,这里的数据库只是一个存储,我们拥有应用程序中的所有领域复杂性。

      例如,我们还让我们的客户决定哪个属性是表单标题,因此如果firstname 是表单标题,他们会将跨越整个应用程序的内存中参数设置为类似于Params.InMemory.TitleAttributeId = <user-defined-id>

      我希望这能让您对类似场景的生产实现有所了解。

      【讨论】:

        【解决方案4】:

        我正在为客户做类似的事情。我创建了一个 JSON FieldType,它包含一个复杂对象的整个 JSON 流和一个包含我的 C# 模型类的 FQTN (FullQualifiedTypeName) 的字符串。

        通过使用自定义 New-、Edit- 和 Display-Forms,我们确保我们的自定义对象以正确的方式呈现,以获得最佳用户体验。

        为了将复杂 C# 模型中的字段提升到 SharePoint 列表,我们构建了类似于 Microsoft 在 InfoPath 中所做的东西。用户可以从 Complex C# 类型中选择 Properties 或 MetaData,这将自动提升到托管 SharePoint 列表。

        JSON 的一大优势在于,它比 XML 更小,更易于在网络世界中使用。 (JavaScript...)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-07-13
          • 1970-01-01
          • 2011-10-18
          • 1970-01-01
          • 2012-03-30
          • 2014-01-12
          • 2017-12-17
          相关资源
          最近更新 更多