65.9K
CodeProject 正在变化。 阅读更多。
Home

CRUD 应用程序的最小元模型

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (70投票s)

2008 年 8 月 17 日

GPL3

26分钟阅读

viewsIcon

282668

对通用 CRUD 应用程序所需的最小元数据(数据库映射和用户界面)进行概述,以待办事项列表为例。

引言 

对象模型和关系模型之间的差异早已被注意到,并被称为对象-关系阻抗不匹配

然而,很少有人注意到的是,通常被称为 CRUD(创建、读取、更新、删除)的简单应用程序有效地展示了关系模型和 UI 结构之间的惊人相似性。一个微不足道的观察是数据库运算符和 CRUD 函数之间的对应关系:Create/Insert, Read/Select, Update/Update, Delete/Delete。

本文的主要思想是探索一种 UI 组件模型,该模型通过直接将 UI 模型链接到数据库而无需经过任何中间对象表示,从而使阻抗不匹配变得无关紧要。

我们认为这里的关键概念是 UI 元数据的表示,并且通过一套合适的底层 UI 小部件,大多数 CRUD 应用程序都可以有效地设计而无需手动编码。全功能应用程序的自动代码生成的初步步骤似乎确实表明,简单应用程序(在我们的例子中是 CRUD)可以自动构建(甚至可以动态构建)。

在本文中,我们将以“待办事项列表”应用程序为例,收集所有必要的信息来完整描述 UI 和数据库映射,以便添加、查看、编辑、删除和搜索记录。这些信息称为 UI 元数据(关于 UI 数据的数据),其结构称为元模型(模型之模型,或元数据之模型)。

理想情况下,元数据应该只包含 CRUD 应用程序之间不同的部分,并且尽可能减少冗余。所有应用程序都相同的代码应该是可重用的。

我们需要考虑的元模型的不同问题是

  • 数据库映射
  • UI 表单
  • 字段类型
  • 元素行为
  • 元素定位
  • 元素分组 
  • 元素外观

 

转述 Eric. S. Raymond 在《大教堂与集市》中的原话,“智能数据结构和笨拙的代码比反之效果好得多”,在我们的例子中,我们可以说“智能数据结构和笨拙的代码生成比反之效果好得多” Wink | ;-)

元模型是应用程序定义的结构;因此,在那里做出的决定对代码的数量和复杂性有着巨大的影响。

数据库映射

用于代码生成的数据库映射在映射所有可能的数据结构和连接类型时可能非常复杂。我们不会试图重新发明 Hibernate,而只是看看生成所有必需的 CRUD SQL 所需的最小元数据。

为了保持元数据简单,我们可以使用约定并坚持尽可能少的模式。在 CRUD 的有限范围内,我们可以一致地使用名为“ID”的整型(或长整型)主键列,非空且自动递增。当然,还有其他的命名约定和技术,您可以选择将主键命名为“<表名>ID”而不将其设置为自动递增,但这最终会导致更多的代码和元数据(主键列名、数据类型、递增...)。重要的是坚持一个约定,这样我们就无需为每个实体定义主键和连接,也无需编写所有类型的连接。

对于我们的“待办事项列表”示例,我们需要如下数据库架构

要操作上述架构中的数据,可以使用不同的 SQL 语法,SQL 可以动态生成或一次性编写到存储过程中。我们基本上需要如下 SQL 代码

Create

INSERT INTO EVOL_ToDo (ID, Title, Duedate, PriorityID, CategoryID, Complete, Notes)
			VALUES (...)

 

读取

SELECT t.ID, t.Title, t.Duedate, t.PriorityID, t.CategoryID, t.Complete, t.Notes,
			EVOL_ToDoPriority.name AS Priority, EVOL_ToDoCategory.name AS Category 
			FROM EVOL_ToDo t 
			left join EVOL_ToDoPriority on t.PriorityID=EVOL_ToDoPriority.ID 
			left join EVOL_ToDoCategory on t.CategoryID=EVOL_ToDoCategory.ID 
			WHERE ... 
			ORDER BY ... 

 

更新

UPDATE EVOL_ToDo 
		SET Title=..., DueDate=...
		WHERE ID=...

 

删除

DELETE FROM EVOL_ToDo  
		WHERE ID=...

 

此外,我们还需要以下两个简单的查询来填充任务类别和优先级的下拉列表及其值列表
SELECT ID, name FROM EVOL_ToDoPriority ORDER BY ID

SELECT ID, name FROM EVOL_ToDoCategory ORDER BY name

为了生成所有这些 SQL,我们只需要以下信息(假设所有表都使用“ID”作为主键)

驱动表 EVOL_ToDo
字段
  • ID - 主键 - int
  • Title - nvarchar
  • Duedate - datetime
  • PriorityID - int (LOV 表 = EVOL_ToDoPriority, 显示列 = name, 别名 = Priority, 排序依据 = ID)
  • CategoryID - int (LOV 表 = EVOL_ToDoCategory, 显示列 = name, 别名 = Category, 排序依据 = name)
  • Complete - bit
  • Notes - nvarchar
默认列表顺序 Duedate, PriorityID

到目前为止,所有这些元数据都可以直接从数据库中获取,目前尚不需要外部映射。它可以与所有数据库操作的存储过程名称一起完成。为了构建相应的用户界面,将需要更多的元数据。然后,拥有一个单独的结构(元模型)来存储我们的元数据将是有意义的。

UI 表单

为了与我们的数据库表进行交互,我们将需要几种不同的表单(通常称为模式或视图)。这些对于所有 CRUD 应用程序都是相同的:列表、查看、编辑和搜索……可能还有一些额外的表单,如高级搜索、图表、批量更新、导出和保存的选择。

视图

一次显示一条记录的所有字段以供查看。 


 
未使用。

一次显示一条记录的所有字段以供编辑。 


 
列表

显示多行记录最重要的字段。


 
Charts

绘制一些数据图表。


 
导出

将选择导出为标准格式(Excel、HTML、CSV、XML 或 SQL),一次或多次记录。  


 
搜索

用于搜索记录的示例查询表单。


 
批量更新

一次更新多条记录。


 
高级搜索

用于高级查询的表单,例如“电话号码以 415 开头”或“用于财务和业务类别”…… 


 
选择

预设查询列表。


 
登录

用户登录屏幕。


 

在当今大多数 Web 应用程序中,每个模式都是一个不同的网页。在最近的 Web 2.0 富互联网应用程序中,导出、搜索和高级搜索模式通常是模态对话框。此外,有时我们会看到带有两个不同框架的单页应用程序,用于列表模式和编辑或查看模式(Microsoft Outlook 风格)。

无论您打算为每个模式使用一个页面,还是“页面即应用程序”,模式仍然存在,并且可以使用相同的建议元模型(和相同的模型)来描述它。

字段类型

对于每个字段,模型不应描述每个模式的每个细节,而应使用模式。例如,日期字段在编辑模式下将显示为带有日期选择器按钮的文本框,但在查看模式下将显示为单个字符串。将字段定义为“日期”应该足够了,无需为每个日期字段描述文本框、按钮和弹出日历。

字段类型不再仅仅是数据类型,而是成为“行为类型”或“UI 类型”。例如:URL、电子邮件或电话号码的字段对用户来说是不同类型的,因为它们的行为不同,但它们对数据库来说是相同的数据类型(varchar 或 nvarchar)。我们需要将模式与每个字段类型关联起来。

字段类型列表应至少包括以下内容

布尔值

布尔字段是“是/否”值,显示为复选框。布尔字段存储为数值(是=1,否=0 或 null)。最有效的数据库列类型是 bit。

编辑 查看 列表
search 高级搜索

日期、日期时间、时间

日期在编辑模式下显示为带有日期选择器的输入框,在其他模式下显示为格式化字符串。日期选择器的 Javascript 是一个外部 JS 文件,可以自定义。可能的数据库列类型是 datetime 或 smalldatetime。

编辑 查看 列表
search 高级搜索

十进制、整数

这些类型用于数值。Decimal 可以存储为数据类型 money 或 decimal。Integer 可以是 smallint、int、bigint…

编辑 查看 列表
search 高级搜索

文档

文档在查看模式下显示为下载链接,在编辑模式下显示为带有上传按钮的文本框,在搜索和高级搜索模式下显示为复选框。与图像一样,文档存储在文件服务器上,并且只有文件名存储在数据库中。

编辑 查看 列表
search 高级搜索

电子邮件、URL

文本值在编辑模式下显示为文本框,在其他模式下显示为超链接。这些可以存储为 varchar 或 nvarchar。

编辑 查看 列表
search 高级搜索

公式

SQL 公式或子查询。计算 SQL 输入在字段的 dbcolumn 属性中。公式类型的字段不能由用户编辑。

公式字段示例

<field type="formula" readonly="1" label="Photos"
	format="0 'photos'" dbcolumnread="NBphotos"
	dbcolumn="SELECT COUNT(*) FROM EVOL_Photo P WHERE 
	P.albumid=T.id" ...  /> 
编辑 查看 列表
search 高级搜索

HTML(富文本格式)

“html”字段类型用于显示富文本格式(RTF)或 HTML。它使用 TinyMCE 小部件在浏览器中进行 WYSIWYG 编辑。

编辑
查看
search
列表
高级搜索

图像

图像在查看模式下按原样显示,在编辑模式下显示为带有上传按钮的框,在搜索和高级搜索模式下显示为复选框。图像存储在文件服务器上,只有文件名作为 varchar 或 nvarchar 存储在数据库中。

编辑 查看 列表

search 高级搜索

lov(值列表)

值列表是在编辑模式下显示为下拉列表的选项,或在查看模式下显示为所选字符串。它们对应于数据库中的辅助表连接,并作为次表主键的数字存储在驱动表中。

通过使用字段的某些属性,它可以成为多对多关系而不是一对多关系。

编辑 查看 列表
search 高级搜索

文本

此类型是最常用的。它在编辑模式下显示为文本框。它是一个存储为 varchar 或 nvarchar 的字符串。

编辑 查看 列表
search 高级搜索

多行文本

这些类型的字段显示为大型文本框(HTML“textarea”),并且可以跨越多行。它们可以存储为 text、varchar 或 nvarchar。

编辑 查看 列表
search 高级搜索

我认为上面的列表是构建应用程序所需的最小字段类型集。当然,如果您的应用程序需要,可以添加更多字段类型。例如,IP 地址、颜色、数据大小、温度或富文本……可以作为特殊小部件实现。SalesForce 提供了“百分比”和“电话”的特定字段类型;它还提供了关系字段类型,但这些也可以被视为“特殊值列表”。

您可以实现略有不同的模式。好处是,如果您构建一个元数据驱动的应用程序,您只需要更改一次代码,所有页面都会相应更改。如果您使用全文搜索,您可能希望添加“包含单词”。

在高级搜索中添加“Is null”和“Is not null”(可能根据您的用户称为“Is empty”和“Is not empty”)也很有用(这仅对必需字段有用)。

大多数字段类型映射到单个数据库列,但值列表(LOV)字段映射驱动表中的一个键列,并需要连接到辅助表。类型为“公式”的字段可能映射到子查询,或者根据实现由数据库或 UI 计算。

对于我们的“待办事项列表”示例,我们需要以下字段

  • 标题(文本)
  • 截止日期(日期)
  • 优先级(值列表)
  • 类别(值列表)
  • 完成(布尔值)
  • 备注(多行文本)

 

元素行为

任何 CRUD 应用程序的工具栏根据定义都将是相同的。也许我们应该称之为“SCRUD”,额外加上一个“S”表示“搜索”。它也可能有一个“克隆”按钮,这对于数据输入非常有用。其中一些图标可能会在 Web 表单中重复显示为按钮或链接。

许多客户端交互代码可以是通用的,并且不需要任何额外的元数据。例如,面板可以折叠,并且代码可以用于待办事项列表或联系人管理应用程序。

字段类型已经暗示了很多行为,但我们仍然需要为每个字段引入更多元数据

  • 验证规则:必需、最小值、最大值、正则表达式、最大长度……
  • 安全:只读
  • 标记属于模式:所有字段都将出现在编辑和查看模式中,但搜索、高级搜索和列表模式应只包含字段的子集。
  • 有时在特定模式下更改特定字段的外观或行为:标签-编辑、标签-搜索、帮助、可选……

为我们的“待办事项列表”示例添加行为信息后,我们现在有了以下字段定义

  • 标题(文本):必需,最大长度=255 个字符
  • 截止日期(日期)
  • 优先级(值列表):必需
  • 类别(值列表)
  • 完成(布尔值):labellist="C."(在列表中使用缩写标签)
  • 备注(多行文本):最大长度=1000 个字符,高度=6

 

虽然我们的示例中不需要,但我们可以预期需要自定义验证。元数据应允许指定自定义 JavaScript。

元素定位

使用我们现在为示例收集的元数据和字段类型模式,我们可以如下呈现编辑表单。

只要屏幕上的字段数量不多,这完全没问题。对于字段数量较多的应用程序,这种布局会导致用户进行大量垂直滚动。此外,当字段在屏幕上直观地分组到面板中时(可能还有选项卡,在元数据中可以简单地视为不同类型的面板),用户会感觉更轻松。

最常见的定位策略是决定整个页面的特定列数。标签可以位于字段的左侧(在自己的列中),如上一个屏幕截图所示,或者位于每个字段的上方,如下一个屏幕截图所示。这在地址等情况下并不理想,因为在每一行上显示不同数量的字段并在同一行上显示不同宽度的字段要好得多,如下所示

让我们用待办事项列表示例进行练习。假设我们可以随意定位元素,我们可以将字段组织成 2 或 3 组。这似乎微不足道,但我还是会说,因为它很重要而且并非总是做到:字段的组织应匹配用户的思维模型,而不是开发者的。

2 个面板组织:任务和状态

或 3 个面板组织:任务、状态和备注

有几种指定屏幕上元素位置的方法。我们可以指定每个元素的顶部和左侧坐标,但每次我们删除或添加元素时,我们都需要更改其他元素的坐标来重新组织表单。

我最喜欢的定位方案是“流动定位”,因为它每个元素只需要一个变量:其宽度。此外,在添加或删除元素时,无需对其他元素进行任何更改。此外,它可以以“容错方式”实现,任何大于 100% 的值都将被视为 100%;宽度小于 100% 的字段位于两个宽度为 100% 的字段之间也将表现为 100%。此外,它支持像前面地址示例这样的情况。

字段和面板(组)的组织以相同的方式描述。元素按顺序放置,从左到右,直到达到 100% 的宽度。一旦达到最大宽度,下一个面板将出现在前一组面板下方。

选择 3 个面板表示,并使用“流动定位”方案,我们得到以下描述

 

  • 面板:任务 62%
    • 字段:标题 100%
    • 字段:截止日期 40%
    • 字段:优先级 60%
  • 面板:状态 38%
    • 字段:类别 100%
    • 字段:完成 100%
  • 面板:备注 100%
    • 字段:备注 100%

 

请注意这个方案是多么极简:通过保持元数据的结构(元素顺序和字段嵌套到面板中),并使用 100% 作为默认宽度,我们只需要 4 个数字即可在表单上定位所有元素(字段和面板)。

编辑和查看模式遵循相同的定位。对于其他模式,字段是否出现取决于属性 search(用于搜索)、searchadv(用于高级搜索)和 searchlist(用于列表)。元数据中存在的所有字段都会出现在导出模式中。

顺便说一句,我选择 62%-38% 的比例而不是更常见的 50%-50%,因为它符合黄金比例,该比例被认为是更美观的。如果它适用于古希腊建筑师、达·芬奇和法国印象派画家,那么它也应该适用于应用程序屏幕……而且它的编码难度并不比其他比例大。

标准比例:50% - 50%。

黄金比例:62% - 38%

我们可以以递归或分形的方式应用黄金比例,通过在 62% 和 38% 的两列中将其应用于面板内的字段。区别很微妙,但在潜意识层面,用户应该对让他们想起周围环境或身体的比例感到更舒适。 

字段标签定位

在他的最新著作《Web 表单设计:填空》中,Luke Wroblewski 用一整章来讨论标签定位。为了提高可用性,我决定遵循他的指南。

他提出的最佳实践之一(我以前没想到过)是:“当考虑应用程序中不同表单的不同标签对齐方式时,请考虑上下文与一致性之间的权衡。”

因此,我对不同表单使用了不同的标签定位方案,如下所示

  • 查看和编辑表单的顶部对齐标签,因为它们“标签和输入字段非常接近,处理它们所需的工作量很小”。
  • 搜索和高级搜索表单的左对齐标签,因为它们“更容易扫描表单所需的信息”。
  • 带有输入的导出表单标签

元素分组

如前所述,当字段很多时,将它们分组到面板中很有用。现在,当面板太多而无法在不滚动的情况下适应屏幕时,我们应该将它们分组到选项卡中。选项卡可以节省大量屏幕空间,并帮助用户不被过多信息一次性压垮。

元素外观

在当今的 Web 应用程序中,元素的外观几乎总是使用 CSS 设置。我们可以为所有字段定义一个默认 CSS 类,为只读字段定义另一个类。当然,可以并且有时有必要更进一步,为不同类型的字段或不同模式设置不同的类。

最低限度,我们应该具有以下 CSS 类

对于未通过验证的字段,我们应该添加“FieldInvalid”CSS 类。通过将其与“Field”CSS 类结合使用,我们可以减少所需的 CSS 类数量。

没有必要在模型中指定工具栏、按钮、字段标签等所有应用程序都相同的 CSS 类。实际上,通过使用一组默认 CSS 类,并且只指定我们想要特殊的元素类,我们节省了大量时间和精力,同时也强制了应用程序的外观和感觉一致性。

此外,我们应该在元数据中添加一种方法来指定实体图标的文件名。

在我们的示例中,为了使其脱颖而出,我们将字段“Title”的类名从默认的“Field”更改为“FieldMain”。我们还将为实体指定一个图标

保持简单

到目前为止,我们已经研究了描述 CRUD 应用程序所需的要素。我们现在可以决定为数据库映射使用一个 XML 文档(类似于 Hibernate 的),为每个 UI 表单使用一个 XML 文档(通过字段/属性名引用数据库映射文档)。这对于复杂的应用程序可能是必需的,但在 CRUD 的范围内,我们可以将所有这些文档“折叠”成一个。

尽量减少 XML 文档的数量并避免冗余将使维护更容易,并避免由于文档中的拼写错误或不匹配而导致的许多潜在的“元数据错误”。

我们现在可以定义我们“待办事项列表”应用程序的编辑表单的元素,为每个字段添加其数据库映射信息,并标记我们希望在搜索、高级搜索和列表表单中显示的字段。这将使我们获得一个单一的 XML 文档,该文档可用于生成所有 SQL 和所有 UI 表单。

<?xml version="1.0" encoding="UTF-8"?>
<form label="To Do"  xmlns="http://www.evolutility.com">
  <data entity="task" entities="tasks" icon="m-todo.gif"
			dbtable="EVOL_ToDo" dborder="PriorityID, duedate" />
	<panel label="Task" width="62" >
		<field type="text" label="Title" 
			dbcolumn="title"
			required="1" cssclass="fieldmain" maxlength="255" width="100" 
			search="1" searchlist="1" searchadv="1" />
		<field type="date" label="Due Date" 
			dbcolumn="duedate" 
			maxlength="10" width="40" 
			search="1" searchlist="1" searchadv="1" />
		<field type="lov" label="Priority" 
			dbcolumn="PriorityID" dbcolumnread="Priority" 
			dbtablelov="EVOL_ToDoPriority" dbcolumnreadlov="name" dborderlov="ID"
			required="1" width="60"  
			search="1" searchlist="1" searchadv="1" />
	</panel>
	<panel label="Category" width="38">
		<field type="lov" label="Category" 
			dbcolumn="CategoryID" dbcolumnread="Category" 
			dbtablelov="EVOL_ToDoCategory" dbcolumnreadlov="name" dborderlov="name"
			width="100" 
			search="1" searchlist="1" searchadv="1" />
		<field type="boolean" label="Complete" labellist="C." 
			dbcolumn="Complete"
			width="50" img="checkb.gif"  
			search="1" searchlist="1" searchadv="1" />
	</panel>
	<panel label="Notes" width="100">
		<field type="textmultiline" label="" labeledit="Notes" labellist="Notes" 
			dbcolumn="Notes"
			maxlength="1000" width="100" height="6"  
			search="0" searchlist="0" searchadv="1" />
	</panel>
</form> 

 

此外,我认为拥有良好的默认值非常有益。这样,如果需要,可以进行更改,但用户可以依赖默认值而无需了解它,直到需要时。这不会简化元模型,但可以使模型更小。

尝试在 Evolutility.com 上实时查看由此元数据生成的“待办事项列表”应用程序。

CRUD 元模型

现在让我们收集前面段落中遇到的元数据的详尽列表,并提出一种正式语言来完整描述 CRUD 应用程序。我们还将添加在我们示例中不需要但对于更复杂的应用程序很有用的信息。

正如我们刚才看到的,一个 CRUD 应用程序可以通过单个 XML 文档来定义。这个 XML 文档由一个 form 元素组成,其中包含一个 data 元素,以及一个或多个 panel 元素,其中包含一个或多个 field 元素。

form 元素

form 是根元素。它不代表一个单独的 Web 表单,而是代表所有必需的 Web 表单(编辑、查看、列表、搜索、高级搜索、导出)。它具有可选属性 labeldescriptionversion,以及必需的命名空间 xmlns

form 元素包含一个 data 元素和一个或多个 panel 元素。字段是否显示在每个 Web 表单上取决于属性 search searchlistsearchadv

 

data 元素

data 元素指定组件使用的数据库对象集:驱动表、存储过程;以及相关的图标和屏幕名称。

entity 数据库对象的用户对象名称(例如:“task”,用于待办事项列表应用程序)。
entities entity 的复数形式(例如,待办事项列表的“tasks”)。
icon 记录图标的文件名(所有记录都使用相同的图标)。
例如:icon ="Metamodel_for_CRUD/todo.gif"
dbcolumnlead 用作用户记录标识符的数据库列(非主键)。
例如:dbcolumnlead="TITLE"
dbcolumnpk 用作记录标识符的主键列名。
例如:dbcolumnpk="ID"
dbtable 应用程序的驱动表名。
dbwhere SQL where 子句,用于限制要操作的数据集。
dborder 要包含在“order by”SQL 子句中的列名列表。这是默认排序选项。
spdelete 用于删除记录(或将其标记为已删除)的存储过程的名称和参数。
spget 用于检索特定记录的存储过程的名称和参数。
splogin 用于检查用户凭据的存储过程的名称和参数。例如:splogin="EvoSP_Login @login, @password"
sppaging 用于分页搜索结果的存储过程的名称和参数。

panel 元素

panel 元素用于在屏幕上将字段在视觉上分组。

cssclass 面板的 CSS 类。默认值为 "Panel"。
cssclasslabel 面板标题的 CSS 类。默认值为 "PanelLabel"。
label 面板标题。
optional 如果面板中的所有字段都是可选且为空的(仅在查看模式下),则跳过显示该面板。
width 面板在表单总宽度中所占的百分比。
例如:width="100" 表示全宽度。

tab 元素

tab 元素可用于将面板分组在一起,并一次查看一组。此元素是可选的。

cssclass 选项卡的 CSS 类。默认值为 "Tab"。
cssclasslabel 选项卡标题的 CSS 类。默认值为 "TabLabel"。
label 选项卡标题。

field 元素

field 元素同时表示屏幕上的字段和数据库列。它是最常用的元素,也是属性最多的元素。对用户隐藏的数据库列(如驱动表的主键)未声明。

cssclass 特定字段的 CSS 类名(如果我们想覆盖默认值)。 
cssclasslabel 特定字段标签的 CSS 类名(在编辑和查看模式下)。默认值为 "FieldLabel"。
dbcolumn 字段的数据库列(SQL 名称)。
dbcolumnread 数据库列别名。仅对 LOV 类型的字段有用,否则 dbcolumnread 必须与字段的 dbcolumn 相同。
dbcolumnreadlov 在列表中显示的列。默认值为 "name"。
dborderlov 用于对下拉列表中的值进行排序的列名(或逗号分隔的列名列表)。
dbtablelov 包含下拉列表可能值的数据库表。
dbwherelov 额外的 SQL where 子句,用于限制值列表。
defaultvalue 创建新记录时显示的字段的默认值。
format 字段格式(适用于布尔值、日期、十进制或整数类型的字段)。
例如:format="'$'#,##0.00"
height 字段的高度,以行数表示(除 TextMultilines 类型字段外,默认为 1)。
帮助 字段的帮助工具提示(仅在编辑模式下使用)。
img 要显示的图像(适用于“boolean”或“url”类型的字段),在编辑或查看模式下。
jsvalidation 字段验证的 Javascript 方法名称。
label, labeledit,
labellist
字段标题(在不同模式下)。只有 label 是必需的,如果未指定,则为所有其他模式的默认值。
link 强制字段显示为指向另一个网页的链接。它可以使用的变量如下:@itemid, @userid, @fieldid。
linklabel 显示一个句子或图像作为链接。字符串中的 @fieldvalue 在运行时将被字段值替换。
linktarget 直接点击链接在新浏览器中打开。
max  字段允许的最大值。
maxlength   字段值允许的最大字符数。
min

字段允许的最小值。  

minlength   字段值有效的最小字符数。
optional 决定字段在为空时是否显示(仅适用于查看模式)。
readonly readonly=1 表示字段的编辑。 readonly=2 表示字段的编辑,但允许在插入时输入。 
regexp 用于验证字段值的正则表达式。
required 确定保存记录是否需要该字段。将自动生成客户端验证的 Javascript。
search 确定字段是否显示在搜索表单中。
searchadv 确定字段是否显示在高级搜索表单中。
searchlist 确定字段是否作为搜索结果列表的列显示。
type 字段的类型。如前所述,可能的值是:boolean(是/否)、date、datetime、decimal、document、email、formula、image、integer、lov(值列表)、text、textmultiline、time 或 url。
width

字段在所属面板中的宽度百分比。

存储元数据

现在我们有了元模型,我们需要存储元数据。自然,我们有两个常见的选项:XML 或数据库。这就是我们获得简单元模型好处的地方:越简单的元模型,XML 或数据库字典的结构就越简单。

使用 XML 文档

  • 优点:灵活,独立,易于安装,易于修改。
  • 缺点:有时在文档之间冗余。
  • 有就好了:用于验证的 XSD。

使用数据库字典

  • 优点:集中化,可以混合数据和元数据(尽管这可能很危险),可以使用相同的应用程序来编辑数据和元数据。
  • 缺点:数据库字典的开销,难以在没有自定义工具的情况下进行编辑。
  • 必需:数据库架构(下面是一个简单的)。

  

上述架构可以通过将“EvoDico_Field”表拆分为两个单独的表来增强,一个用于数据库映射,一个用于每个字段的 UI 信息。当同一表被不同用户组访问,并且某些用户被限制在字段的子集时,这将特别有用。

关于实现

提议的元模型相对简单,非常适合 CRUD,并且其所有模式都能协同工作。其他元模型和不同的模式集是绝对可能的。根据您想要达到的控制和可定制性级别,您可能希望使用更复杂的。

保持简单有许多优点。这样,非程序员就可以查看应用程序描述并进行修改,而无需经过大量的学习曲线或阅读文档(我们知道大多数人不会)。

关于元数据驱动的应用程序,最有趣的问题可能是何时执行代码生成。我们应该使用元模型在设计时生成代码(然后编译运行),还是可以在运行时生成代码并让应用程序自我修改?

UI 的描述方式可以在任何平台上实现。

实现为 ASP.net Web 控件

我创建了一个名为 Evolutility 的开源 CRUD 框架,它是 C# 和 Javascript 在 ASP.net 中使用的元模型的实现,支持 SQL Server 或 MySQL。它可以处理存储在 XML 中或直接存储在数据库中的元数据(允许应用程序自我修改)。感谢用户/贡献者,它提供了以下语言的版本: 加泰罗尼亚语 简体中文 丹麦语 英语 波斯语 法语 德语 印地语 意大利语 日语 葡萄牙语 罗马尼亚语 西班牙语,以及 土耳其语

实时示例应用程序可在 www.evolutility.com 找到。Evolutility 项目是源代码(在 Affero GPL v3 下,带有双重许可)。尽情享用……也许改进它并贡献您的代码。

在此文章 使用 Evolutility 进行的即时代码生成向导和 CRUD 应用程序来构建其他 CRUD 应用程序 中,提供了此元模型的有效实现及示例应用程序。

在此处下载最新版本的 Evolutility Get Evolutility at SourceForge.net

实现为一套 Backbone 视图

我还开始了一个更现代的版本,使用了 Backbone、Bootstrap 和 jQuery。代码和一个实时演示可在 GitHub 上找到。

历史

2008 年 8 月 17 日 - 初始文章

2008 年代码生成竞赛获奖(三等奖)

2009 年 5 月 27 日 - 更新

元模型

  • 在“form”元素中添加了属性 label、description 和 version,以及 xmlns。
  • 在“data”元素中添加了属性 dbcolumnlead 和 pkcolumnname。
  • 在“field”元素中添加了属性 jsvalidation、min 和 max。
  • 添加了“tab”元素。

 

文章

  • 添加了关于字段标签和字段组的段落。
  • 添加了 CSS 详细信息。
  • 最终理解到“is null”和“is not null”是有效的搜索条件。
  • 更新了 UI 表单的屏幕截图,并为字段类型添加了图标。非常感谢 Mark James 的 Silk Icons set
  • 添加了目录。 
  • 添加了本地化演示的链接。
  • 杂项文本编辑。 

2009 年 10 月 13 日 - 小更新

元模型

  • 在“field”元素中添加了属性 minlength。 

文章

  • Evolutility 现在支持 13 种语言。

2010 年 4 月 29 日 - 小更新

  • 添加了新的“批量更新”视图(Web 表单)。

2011 年 12 月 22 日 - 更新

  • 为 HTML(富文本格式)添加了新的字段类型。
  • 新的图表视图(版本越来越不极简……)。
  • Evolutility 现在支持 14 种语言,并增加了波斯语。
  • 新的外观,带有圆角。
  • 杂项文本编辑。 

 

 

© . All rights reserved.