【问题标题】:C# ASP.NET Core building dynamic formsC# ASP.NET Core 构建动态表单
【发布时间】:2017-09-24 22:20:48
【问题描述】:

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

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

我正在考虑创建动态 SQL Server 表、列等,但也许这不是好方法。有人可以建议数据库的外观吗?

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

【问题讨论】:

  • 至少你应该举一个例子。用户将填写什么样的表单?
  • @KumarHarsh:表单是动态的,正如我提到的,系统会自动填写一些常用字段(Id、CreatedDate、Createdby 等)。否则表单应该是动态的这意味着客户可以添加字段(文本框、复选框、下拉菜单、文本区域、日期时间等)
  • 无论你想创建多么动态,它都必须遵循一些特定的域和业务规则。例如,学校的注册表和招标门户之间有很多差异。不可能both.impossible.Also说同一所学校的软件可以为1000所学校定制,每个学校的要求各不相同。这并不意味着它适合招标门户网站或者它是100%动态的。
  • @KumarHarsh:业务规则很简单:允许客户创建和自定义表单。我的意思是想象一个excel文件。在我的示例中,来自 excel 的工作表是表单,而 excel 中的列是我表单中的字段。在一张表中,您可以创建一个包含 10 列的表,用于存储客户信息。您可以添加更多字段或删除默认字段(Id、CreatedBy、CreatedDate 等)以外的字段。然后您创建另一个工作表并存储员工详细信息,您还可以自定义列的数量。现在我想实现相同的逻辑以允许客户动态创建表单。
  • 猜你不明白我的学校 vs Tender 的例子。学校的员工数据或 Tender porta 或者它可以是任何东西。虽然让用户创建动态表单是可以的,但是整个软件必须遵循某些域,即 biz 规则。好的,在一个 UI 中,我允许用户创建表或更改表。然后相应地在另一个动态的 Employee UI 中允许用户填充员工数据。这意味着允许用户在一个 UI 中创建新字段或更改,然后在另一个 UI 中相应地创建动态 UI .因此,对于每个客户,您都可以区分数据库。虽然从 Excel 中汲取灵感是可以的,但它不能是 100% Excel。

标签: c# sql-server asp.net-core office365 asp.net-core-1.0


【解决方案1】:

NoSql 方法似乎是一种简单的方法。如果您仅将数据库视为 IO 设备,它不应该包含任何“业务”逻辑,那么内存成本和内存读取/写入时间 (SSD) 会变得更低这一事实 - 您将没有更多选择来解决您的问题。

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

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

基于该对象,您可以生成带有列表或已创建字段形式的视图。 您可以为具有更多视图生成和数据处理所需数据的字段引入自己的“对象”。

{
    "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 列和一个标识列中保存“原始 json”。
为了处理数据,您可以将其反序列化为Dictionary&lt;string, object&gt;
使用字段对象{ "Name" "CreatedAt", "Type": "DateTime" },您可以将值转换为预期的类型以进行正确的验证和处理。

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

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

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
)

并考虑使用微软版本的 NoSql - DocumentDB

【讨论】:

  • 感谢您的回答。在 NoSql 的情况下,您提到用户可以搜索数据,如何更准确地工作? NoSql 声音是一个好方法我想知道一件事:如果我创建一个查找类型的字段,允许用户以另一种形式从另一个字段获取数据,那么从关系的角度来看,这将如何工作?从源列表中删除数据等?
  • 对于不同形式的表单之间的关系,您可以引入某种“聚合”表单,其中包含很少的表单。根据您的 cmets,您需要构建动态数据库。因此,使用与 excel 相同的方法,但不是将“工作表架构”保存到文件中,而是将其保存到数据库中。使用这种方法,表单和数据之间的所有关系都应该在代码(c#)中处理,而不是在数据库中。将数据库视为 excel 文件。
【解决方案2】:

我会像下面的伪 SQL 那样构建它(表名以粗体显示):

列表:

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:(对输入的数据进行分组 - 如果这些是表中的列,则为每行记录,或者输入表单的数据为单个记录)

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.)

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

【讨论】:

  • 此外,如果您需要允许删除已有数据的列,您可以实现 IsDeletedDeletedDeletedBy。然后通过将IsDeleted 设置为true 来进行软删除。这就是我过去所做的。
猜你喜欢
  • 2011-10-25
  • 2023-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多