C# ASP.NET 核心构建动态表单

C# ASP.NET Core building dynamic forms

我想实现类似于 SharePoint online 的功能,即列表功能。我想创建动态列表添加新列等。用户可以填写表格并保存数据。

瓶颈是数据库,我很难理解应该如何构建它。

我正在考虑创建动态 SQL 服务器 table、列等,但这也许不是好的方法。有人可以建议数据库应该是什么样子吗?

我正在考虑创建一个名为 Lists 的 table 并在其中存储 List 属性。然后是与另一个名为 Fields 的 table 的多对多关系,我可以在其中存储与特定表单相关的所有字段。多对多关系,因为某些字段对于所有表单都是通用的,例如:Id、CreatedBy、Created、Modified、ModifiedBy 等。现在困难的部分来了。我应该在哪里存储实际数据?我是否应该创建另一个名为 FormData 的 table 并将数据存储在其中?它与ListsFieldstables应该有什么关系?

我会像下面的伪SQL(table 粗体名称)构造它:

列表:

Id int
Name nvarchar(255)  -- list name
CreatedBy, Created, Modified, ModifiedBy (audit for the List creation/changes)

列表字段:

Id int
ListId int  -- foreign key to associated list
Name nvarchar(255)  -- column name
DataType nvarchar(3) -- abbreviation of data type - string, integer, float, bool etc.
Sort int -- column order
CreatedBy, Created, Modified, ModifiedBy (audit for List Field creation/changes)

这定义了列表本身。

现在当用户输入数据时...

ListEntries:(对输入的数据进行分组 - 如果这些是 table 中的列,则每行一条记录,或者输入数据的单个记录表格)

Id int
ListId int  -- foreign key to associated list
CreatedBy, Created, Modified, ModifiedBy (audit for Data creation/changes)

ListValues:(每个字段中输入的实际数据)

Id int
ListEntryId int  -- foreign key to the associated group of values
ListFieldId int  -- foreign key to associated field
Value nvarchar(max)  -- data (stored as text regardless of whether text or not - it could be int, double etc.)

就我个人而言,我不会尝试回收公共字段。在每个 table 上都有审计字段可以很好地跟踪更改(如果需要),并且在查看记录时很容易理解。我没有审计单个值,因为通常将更改作为一个集合进行跟踪就足够了(通过 ListEntries)。当然,如果需要的话,这里也可以进行审计。

NoSql 方法似乎是一种简单的方法。如果您仅将数据库视为不应该包含任何 "business" 逻辑的 IO 设备,那么内存成本和内存 reading/writng 时间 (SSD) 变得更低这一事实 - 您几乎没有更多选择你的问题。

例如,您可以将字段的集合保存在一个对象中

{
    "key": "form1",
    "fields" : [ "Id", "CreatedAt" ]
}

基于该对象,您可以生成包含已创建字段列表或表单的视图。 您可以为视图生成和数据处理所需的更多数据的字段引入自己的 "object"。

{
    "key": "form1",
    "fields" : [ 
        { "Name": "Id", "Type": "string" }, 
        { "Name" "CreatedAt", "Type": "DateTime" } 
    ]
}

实际数据也可以保存在一个对象中

{
    "formKey": "form1",
    "Name": "FirstName LastName",
    "CreatedAt": "2017-04-23T18:25:43.511Z"
}

在客户端,此数据可以轻松保存为 json 对象并发送到服务器。
在服务器端,您可以将该对象反序列化为 Dictionary<string, object> 并以动态方式处理它

var formEntity = JsonConvert.DeserializeObject<Dictionary<string, object>>(requestBody);

var name = formEntity["Name"].ToString();

如果你紧紧依附于关系数据库,你可以在 NVARCHAR 列和一个标识列中保存 "raw json"。
对于处理数据,您可以将其反序列化为 Dictionary<string, object>.
使用字段对象 { "Name" "CreatedAt", "Type": "DateTime" },您可以将值转换为正确验证和处理的预期类型。

您将能够根据动态字段搜索数据以创建动态报告,用户可以在其中创建自己的报告。

由于字段结构不是动态的,您可以以关系方式保存表单和字段结构。以下是我对 sql 服务器数据库的建议。

CREATE TABLE Forms (
    Id INT IDENTITY(1,1) NOT NULL
)

CREATE TABLE Field(
    Id INT IDENTITY(1,1) NOT NULL,
    Name NVARCHAR(30) NOT NULL,
    TypeName NVARCHAR(30) NOT NULL, -- Or INT -> can represent SqlDbType enum in c#
)

-- many to many relation of Form and Fields
CREATE TABLE FormFields (
    FormId INT NOT NULL,
    FieldId INT NOT NULL,
    PRIMARY KEY (FormId, FieldId)
)

-- because data is "dynamic" it should be saved  as string (json format)
CREATE TABLE FormData(
    Id INT IDENTITY(1,1) NOT NULL,
    FormId INT NOT NULL,
    Data NVARCHAR(MAX) NOT NULL, -- json format
)

并考虑使用 Microsoft 版本的 NoSql - DocumentDB