使用C#和RavenDB进行自定义字段设计

Eri*_*arr 8 c# architecture aggregateroot nosql ravendb

我正面临一个与如何将自定义字段附加到系统中的实体相关的关键设计问题.实体用C#表示并保存在RavenDB中.我们大致跟随域驱动设计的租户,我们的实体是聚合根.

[注意:我想避免围绕DDD方法中的自定义字段等通用功能的适当性进行辩论.假设我们有合法的用户需要附加和向我们的实体显示任意数据.此外,我已经将我的示例设为通用,以说明设计挑战.:)]

我的问题是关于如何最好地布置字段定义和字段值实例.

想象一下我们拥有Book and Author集合根的域.我们希望用户能够将任意数据属性附加到Books和Authors的实例.所以,我们可以用这样的类定义一个自定义字段:

public enum CustomFieldType
{
    Text,
    Numeric,
    DateTime,
    SingleSelect,
    MultiSelect
}

public class CustomFieldDefinition
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public CustomFieldType Type { get; set; }
    public Collection<string> Options { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

附加到Book的 CustomFieldDefinition(CFD)可能具有以下值:

  • Id: "BookCustomField\1"
  • 名称: "FooCode"
  • 类型:文字
  • 描述: "Foo Corp的特殊标识符."
  • 类型:文字
  • 选项: null

我面临的第一个问题是在每本书的实例上存储什么.选择范围从......

低端:

只存储CFD Id和实例值

高端:

存储整个差价合约以及价值

"低端"很糟糕,因为我不能在没有拉入CFD的情况下显示一本书,这是在另一份文件中.另外,如果我以任何方式更改差价合约,我都会更改历史文档中值的含义.

"高端"很糟糕,因为会有很多重复.对于选择列表差价合约,差价合约可能相当沉重,因为该定义包含所有可选择的选项.

第一个问题是...... 每本书的文件应该存储多少?刚好足以显示本书(如果我要允许用户编辑CF值,我必须回到CFD显示选项和说明)?

第二个问题是...... 我应该存储我将一个实体类型的CFD的整个集合存储在一个文档中还是将每个CFD保存在它自己的文档中? 在此输入图像描述

每个CFD作为文档为每个CFD保持简单(特别是当我开始执行诸如停用定义之类的操作时),但是我需要一种方法将Book CFD与Author CFD分开.这也迫使我每当我想编辑实体时为每个附加到实体的CF加载1个文档.

一个文档中给定类型的所有CFD允许我只加载一个文档,但之后我也加载了所有已停用的定义.

第三个问题...... 有没有更好的方法来实现这一点?

第四个问题...... 那里有任何样本或开源解决方案,所以我不必重新发明这个轮子吗?

Mat*_*int 1

既然你在评论中说:

...一年前的书应该显示一年前的自定义字段。

我能看到的只有两个可行的选择。

选项1

  • 自定义字段定义存在于其自己的文档中。
  • 每本书都包含适用于该书的自定义字段定义的副本,以及每个自定义字段的选定值。
  • 它们在书籍首次创建时被复制,但可以根据您的逻辑认为合适再次复制。也许在编辑时,您可能想要获取一个新副本,这可能会使当前选择无效。
  • 优点:独立,易于索引和操作。
  • 缺点:大量自定义字段定义副本。存储需求可能非常大。

选项2

  • 使用临时版本控制包 (免责声明:我是它的作者)。
  • 自定义字段定义仍然存在于其自己的文档中,但会暂时进行跟踪。这意味着对自定义字段的修订将保留在可用历史记录中。
  • 书籍仅包含选定的值。它们不包含定义的副本。
  • 书籍不需要进行临时跟踪,但它们的数据确实需要某种有效日期。也许是“输入”日期。使用任何对你有意义的东西。
  • 账面到差价合约的关系是一种Nt:Tx类型。您可以在此处找到此关系类型的另一个示例。您可能想要了解时间关系的概述,以便理解这一点。请注意,这是一个棘手的主题,并且很快就会变得复杂。
  • 优点:所需的存储空间少得多,因为自定义字段定义数据的重复副本不多。
  • 缺点:学习曲线。处理时态数据的复杂性。需要在数据库服务器上安装自定义捆绑包。

无论选择哪种方式,我都只需在自定义字段定义上保留一个属性,说明它适用于什么类型(书籍、作者等)。