实体设计器
本文将介绍实体设计器、基类实体设计器、从属实体设计器中的可用选项:
实体设计器:在 添加新项 中选择 实体设计(从零开始) 或 实体设计(基于数据库) 后,此设计器将打开。 它允许您创建和配置与 EF Core、SQLSugar、Dapper 或其他 ORM 兼容的实体(目前仅支持 EF Core 6/7/8)。 通常,您为每个数据库表创建一个实体。
实体(基类)设计器:在 添加新项 中选择 基类实体设计 后,此设计器将打开。 它允许您创建和配置可由其他实体继承的基本实体。
与常规实体相比,基本实体没有表/架构和继承映射选项; 没有过滤器、服务和 API 设置; 并且它只能从另一个基础实体继承。
实体(从属)设计器:在 添加新项 中选择 从属实体设计 后,此设计器将打开。 它允许您创建和配置新的自有实体类型。 自有实体是嵌入其所有者(另一个实体)内的实体。
与常规实体相比,自有实体没有表/架构和继承映射选项; 没有过滤器、服务和 API 设置; 并且它不能从任何其他实体继承。
实体设计器、实体(基类)设计器 和 实体(从属)设计器 具有类似的选项。
在下面的章节中,将描述通用选项,而不会提及它属于哪个设计器,除非该选项仅在其中一个或某些实体中可用。
字段设计
实体设置
您可以在 字段设计 选项卡中为实体指定以下基本设置:
显示名称: 实体的显示名称。将在 C# 代码中生成 [DisplayName] 属性。
映射表 > 架构名称:如果使用关系数据库,您还需要指定表架构。 如果此处未指定架构名称,则将使用数据库中的默认架构。
映射表 > 表名称:实体映射到的数据库表。 通常每个实体都需要与一个数据表进行映射。 如果这里没有指定表名,则使用实体类名作为表名。
设置表选项后,将生成以下 C# 代码:
继承自:选择是否从另一个实体继承。默认提供了两个内置的基类实体:
AuditEntity 包含了审计数据相关的属性,新增人、新增时间、修改人、修改时间。继承自这个实体后,自动有这些字段,这些字段的数据会自动更新和维护,不需要用户处理。
MultiTenantEntity 包含了多租户场景中使用的属性,租户ID、新增人、新增时间、修改人、修改时间。继承自这个实体后,自动有这些字段,这些字段的数据会自动更新和维护,不需要用户处理。
继承关系:选择是否使用以下模式映射继承:Table-per-hierarchy (TPH)、Table-per-type (TPT)、Table-per-concrete-type (TPC)。 有关详细信息,请参阅 继承策略。
描述: 实体的描述。 该描述将在 C# 代码中显示为注释。
继承策略
本文内容
继承是指子类继承了父类的特性和行为,使子类对象(实例)具有父类的实例字段和方法,或者子类继承了父类的方法,使子类具有与父类相同的行为。 目前,SnapDevelop 支持三种继承策略:
- Table-per-hierarchy (TPH):每个层次结构一个表,将字段合并并存储到基类表中。
- Table-per-type (TPT):每个类型一个表
- Table-per-concrete-type (TPC):每个具体类型一个表,将基类字段合并并存储到当前表中。
请根据您的业务场景选择继承策略。
本文将简要介绍实体设计文件中继承映射的四种选项以及它们在关系数据库中的不同表现。
注意:无论选择哪种继承策略,根实体都不能是基础实体,同一条继承链上只能有一个继承策略,且主键和继承策略只能在根实体中设置。 根实体指的是继承策略设置的顶端实体。
无策略
当选择 无 时,如果实体是继承的,则将使用默认策略 Table-per-hierarchy (TPH)。
每个层次结构一个表 (TPH)
Table-per-hierarchy(TPH)指的是根实体和子实体的所有字段都列在一张表中,并用一个标识列(Discriminator)来指示这一行数据中存储了哪些子实体数据。
让我们尝试通过以下场景来理解 Table-per-hierarchy (TPH):
假设需要创建一个教育管理系统。 系统中存在三个角色:学生、家长、老师。 他们各自拥有的字段如下:
学生字段:姓名、年龄、性别、入学时间、班级 家长字段:姓名、年龄、性别、联系电话、职业、教育程度 教师字段:姓名、年龄、性别、教学年限、学科
所有角色都具有这三个字段:姓名、年龄和性别。 创建 Person.sde 并向其中添加这三个公共字段,然后为每个角色创建一个实体,并将其余字段相应地添加到各自的实体:Student.sde、Parents.sde 和 Teacher.sde。
将 Person.sde 中的继承映射设置为 Table-per-hierarchy (TPH),并将其他实体的 BaseEntity 设置为 Person.sde。
生成并运行项目后,数据库中会生成一个 Person 表。
Person 表包含三个角色的所有字段以及自动生成的标识列(Discriminator)。 标识列将存储数据行代表的实际实体,即学生、家长或教师。
每个类型一个表 (TPT)
Table-per-type (TPT) 指的是根实体和每个子实体都有对应的表,并通过将子表的主键设置为外键来将子表与父表关联。
我们继续用同样的场景来解释 Table-per-type(TPT):
假设需要创建一个教育管理系统。 系统中存在三个角色:学生、家长、老师。 他们各自拥有的字段如下:
学生字段:姓名、年龄、性别、入学时间、班级 家长字段:姓名、年龄、性别、联系电话、职业、教育程度 教师字段:姓名、年龄、性别、教学年限、学科
创建 Person.sde 并向其中添加公共字段(姓名、年龄和性别),并为每个角色创建一个实体,并将其余字段相应地添加到各自的实体:Student.sde、Parents.sde 和 Teacher.sde。
将 Person.sde 中的继承映射设置为 Table-per-type (TPT),并将其他实体的 Base 实体设置为 Person.sde。
生成 [project].Dal 后,在该项目的 Configurations 文件夹下,根实体和子实体的配置文件都会生成一个 “ToTable” 方法。
项目运行后,数据库中会生成四张表。
Person 表存储公共字段,Student表、Parents表、Teacher表存储各个角色的字段,这三个表的主键都是与Person表关联的外键。
每个具体类型一个表 (TPC)
Table-per-concrete-type (TPC) 指的是根实体和每个子实体都有对应的表,但子表不与父表关联,并且子表包含所有必需字段(包括父表中的字段)。
注意:在 SnapDevelop 中使用 TPC 继承策略时,根实体的主键必须是 GUID 类型。
现在让我们尝试使用相同的场景来理解“每个具体类型一个表”(TPC) 选项:
假设需要创建一个教育管理系统。 系统中存在三个角色:学生、家长、老师。 他们各自拥有的字段如下:
学生字段:姓名、年龄、性别、入学时间、班级 家长字段:姓名、年龄、性别、联系电话、职业、教育程度 教师字段:姓名、年龄、性别、教学年限、学科
创建 Person.sde 并向其添加公共字段(姓名、年龄和性别),并为每个角色创建一个实体,并将其余字段相应地添加到各自的实体:Student.sde、Parents.sde 和 Teacher.sde。
将 Person.sde 中的继承映射设置为 Table-per-concrete-type (TPC),并将其他实体的 Base 实体设置为 Person.sde。
生成 [project].Dal 后,在该项目的 Configurations 文件夹下,根实体和子实体的配置文件都会生成以下代码:
builder
.HasBaseType((Type)null);
项目运行后,数据库中生成如下四张表:Person表、Student表、Parents表、Teacher表。 Person表有公共字段:姓名、年龄、性别,其他三个表有其全部字段(包括公共字段),如下:
字段管理
您可以在 字段设计 选项卡中管理字段:
- 添加字段:将新字段添加到当前字段列表。
- 搜索:按名称搜索当前字段列表中的字段。
- 显示继承的字段:选中此选项时,继承字段将以只读方式显示在当前字段列表下方。
字段颜色
① 白色:该字段为继承字段。
② 绿色:该字段的数据类型设置为引用其他实体的实体类型。
③ 蓝色:该字段的数据类型设置为 Enum 类型,引用枚举文件。
④ 紫色:该字段的数据类型设置为 Compute。
字段设置
您可以在 字段设计 选项卡中为字段指定以下基本设置:
名称:字段的名称。
显示名称:字段的显示名称。将在 C# 代码中生成 [DisplayName] 属性。
字段类型: 字段的数据类型。 例如,Int32 数据类型将在 C# 代码中定义为 int 类型。
集合
当在 字段设计 选项卡中为字段选择 集合 选项时,该字段将转换为集合类型,例如:ICollection
如果没有选择 集合,将会生成以下C#代码: 如果选择 集合,将生成以下 C# 代码: 另外,当选择 集合 时,数据存储 部分中会显示 转换 选项,并且会自动选择为 CollectionToStringConverter。 会自动生成如下 C# 代码,表示当前集合字段(属性)已配置进行值转换(实体上定义的集合字段不能直接存入数据库,必须使用值转换器进行数据转换,例如,字符串集合 List
当选择 可空 选项时,该字段将允许为空值。 例如,当布尔类型的字段被选择为可为空时,该字段的数据类型将被定义为 “bool?”,并且该字段可以具有三个值:true、false 和 null。 是否将当前字段设为必填字段。 当选择此选项时,表示该字段为必填字段。 选择 必要 选项后,可以指定验证失败时显示的消息,C#代码中将生成 [Required] 属性。 指定字段作为实体的主键。 当选择 主键 选项时,C# 代码中会生成 [key] 属性或 HasKey 方法,表示当前字段为主键。 例如,以下表示将 id 字段用作实体的 主键。 如果实体不指定主键,则会生成 [Keyless] 属性或 HasNoKey 方法。 有关更多信息,请参阅 无主键实体。 如果指定多个字段作为主键,则会生成一个复合键,例如下面的 C# 代码表示使用 id 字段和 DateTime 字段作为复合键。 有关详细信息,请参阅 复合主键。 复合主键主要用于需要存储商品的多条信息,但仅根据商品的ID无法实现唯一性的场景。 例如,学校信息系统需要统计每个级别每个学生的绩点 GPA,但仅使用 Student ID 是无法得到这个结果的; 所以增加了 Level 字段,并与学生 ID 结合使用,建立了一个复合主键,这个复合主键保证了每个级别中每个学生的唯一性。 要创建复合主键,请指定如下设置: 代码: 学号 ID 和 Level 构成复合主键。 无主键实体主要用于不需要考虑每条数据唯一性的情况。 例如,一个随机名称表(名称重复与否无关紧要)。 要创建无主键实体,请不要选择 主键 选项。 该实体将标注为“(无键)”。 对于无主键实体,将无法提供需要主键的服务。 代码: 您可以在 字段设计 选项卡中为字段指定以下验证设置: 必要:是否将当前字段设为必填字段。 此选项与当前字段列表上的 必要 选项同步。 正则校验:点击展开 正则校验 输入框,您可以手动输入用于验证数据的表达式,也可以从 常用正则表达式 列表中选择系统预定义的表达式(例如,日期时间、域名、电子邮件、IP 地址、电话、URL 等)。 选择预定义表达式后,您还可以根据需要修改预定义表达式。 当指定 正则校验 选项时,将生成 [RegularExpression] 属性。 正则校验错误:正则校验失败时显示的消息。 (此选项仅适用于内置字段类型。) 设置校验选项后,将生成以下 C# 代码: 默认值:指定数据库列的默认值。 如果插入的行没有该列的值,则将使用默认值。 指定默认值有以下三种方式: 1) 手动输入默认值; 2)通过表达式计算默认值; 3)通过 SQL 语句设置默认值。 某些数据类型(例如 String、Single、Double、Decimal)具有以下选项: 长度:指定字符串字段的最小长度和最大长度,或者数字字段的最小值和最大值。 长度错误:当值/长度无效时将显示的信息。 当指定这些选项时,C# 代码中将生成相应类型的属性。 例如,当字段类型为字符串时,将生成 [StringLength] 属性。 代码: 例如,当字段类型为 int32(或single、double、decimal)时,就会生成 [range] 属性。 代码: 对于 Single、Double 和 Decimal 类型,还可以指定以下选项 值范围:指定值的有效范围。 精度:指定数据库将存储的总位数(包括整数位数和小数位数)以及小数位数。设置这两个值后,就会生成数据的精度供您预览。 代码: 对于 DateTime、DateTimeOffset、TimeSpan 类型,还可以指定以下选项 值范围:指定日期或时间的有效范围。 范围错误:当范围无效时将显示的信息。 对于 Compute 类型,还可以指定以下选项 表达式:指定表达式。 数据类型:指定数据类型。 保存到数据库:是否将该字段包含在数据库中。 如果选中此选项,则该字段将包含在数据库表中。 (仅限实体和从属实体)对于枚举类型,还可以指定以下选项 转换:目前只有 EnumToStringConverter 可选,表示将枚举值转换为数据库中的字符串。 C# 代码中将生成 HasConversion 生成的代码如下: 数据存储 部分下的选项将用于生成和配置实体中相应的属性(我们所说的字段在 EF Core 中称为属性)。 例如,选中 主键 选项后,将为当前字段生成 HasKey 方法。 对于大多数选项,我们将生成属性(也称为数据注释)来表示配置,对于某些特殊选项(例如 主键、索引),我们将生成 Fluent API 来表示配置。Fluent API 配置优先于属性。 保存到数据库:是否将该字段包含在数据库中。 如果不勾选,C# 代码中会生成一个 Ignore 方法,表示该字段从数据库表中排除。 列名:指定数据表中的列名。 实体属性将映射到此列。 列类型:指定数据表中的列类型。 当指定 列名 和 列类型 时,C# 代码中将生成 HasColumnName 和 HasColumnType 方法。 设置并发检查:指定数据列是否进行并发冲突检查,以实现乐观并发控制。 选中此选项后,C# 代码中将生成 [IsConcurrencyToken] 属性。 本文内容 本文简要介绍了如何在 SnapDevelop 中构建关系对象模型及其在 EF Core 和关系数据库中的表示。 有关 EF Core 中关系的更多信息,请参阅 https://learn.microsoft.com/en-us/ef/core/modeling/relationships#definition-of-terms。 您可以在 字段设计 选项卡中为关系配置以下设置: 关系:选择两个实体之间的关系。 映射到:选择要映射到的字段。 删除规则:将生成 OnDelete 方法,其中 DeleteBehavior 参数支持以下值(Cascade、SetNull、NoAction): 生成外键字段:是否生成外键字段。 通过执行表达式自动生成外键字段的值:是否根据指定表达式自动生成外键字段的值。 插入时执行:是否在插入时执行表达式。 更新时执行:是否在更新时执行表达式。 以下部分将引导您完成为不同关系类型配置这些设置。 本节内容 当一个依赖实体必需与一个主体实体关联时,将使用必需一对一的关系。 例如:身份证必需关联一个所有人,并且一个人只能关联一个身份证。 身份证: 人: 代码生成预览: 生成的表结构: 当一个依赖实体和主体实体的一对一关系是可选的情况时,使用可选一对一关系。 例如:部门拥有一个部门负责人,并且一个员工最多只能负责一个部门(部门负责人可以暂时空缺)。 员工: 部门: 代码生成预览: 生成的表结构: 当依赖实体和主体实体为同一实体时,使用自引用一对一关系。 例如:每个部门可能有一个上级部门,每个上级部门也是一个部门,也有上级部门; 该部门和上级部门属于同一个部门实体。 部门: 代码生成预览: 生成的表结构: 当主体实体使用复合主键时,依赖实体也必须是具有相同属性数的组合键。 例如:身份证以身份证号和区域信息作为复合主键,则一个用户也需要以身份证号和区域信息作为外键。 身份证: 人: 代码生成预览: 生成的表结构: 可以将关联依赖实体的外键作为主体实体的主键。 例如:一个表示管理者的实体,每位管理者关联一个员工。 代码生成预览: 生成的表结构: 本节内容 当多个依赖实体必需与一个主体实体关联时,将使用必需一对多的关系。 例如:回帖必需关联一个博文,并且一个博文可以关联多个回帖。 博客: 帖子: 代码生成预览: 生成的表结构: 当主体实体和多个依赖实体的一对多关系是可选的情况时,使用可选一对多关系。 例如:一个部门拥有多个员工,并且一个员工只能属于一个部门(员工也可以没有所属部门)。 员工: 部门: 代码生成预览: 生成的表结构: 当依赖实体和主体实体为同一实体时,使用自引用一对一关系。 例如:多个部门可能有相同的上级部门,并且该部门和上级部门属于同一个部门实体。 代码生成预览: 生成的表结构: 当主体实体使用复合主键时,依赖实体也必须是具有相同属性数的组合键。 例如:身份证以身份证号和区域信息作为复合主键,并且身份证所有者的地址信息表可以存在多条记录。 身份证: 人员地址: 代码生成预览: 身份证: 人员地址: 生成的表结构: 本节内容 多对多关系与一对一和一对多关系的不同之处在于,它们不能简单地用外键来表示,而是需要一个新的实体类型来“联接”关系的两端 。 这称为“联接实体类型”,最终映射到关系数据库中的“联接表”。 此联接实体类型包含外键值对,其中一对指向关系一端的实体,另一对指向关系另一端的实体。 因此,每个联接实体和联接表中的每一行都表示关系中实体类型之间的关联。 当两个实体之间存在多对多关系时,实体设计器会自动创建一个表示两者关系的属性(如下所示)。 同时创建一个新的联接实体类型: 当两个实体可以多次相互关联时,就会出现多对多关系。 例如:一篇文章可以有多个分类,一个分类也可以被多篇文章选中。 文章: 类别: 代码生成预览: 生成的表结构: EF Core 7 中引入了单向多对多关系,该关系在早期版本中是使用专属导航来实现的。 文章: 类别: 无需进行任何额外配置。 EF Core 上下文配置(EF Core 6 和 EF Core 7 略有不同): EF Core 6: EF Core 7: 生成的表结构: 在多对多关系的两端使用相同的实体类型称为自引用多对多。 例如:每个人有多个 Parent 和多个 Children,它们共用 Person 实体表示。 人: 代码生成预览: 生成的表结构: 描述: 字段的描述,在 C# 代码中显示为注释。 您可以在 字段设计 选项卡中为索引指定以下设置: 添加索引:将新索引添加到当前索引列表。 名称:索引的名称。 字段:选择一个或多个字段用作索引。 唯一:指定是否对索引进行唯一性验证。 当选择字段并勾选 唯一 时,C# 代码中会生成如下 HasIndex 和 IsUnique 方法,表示将所选字段设置为唯一的 索引。 代码: 您可以对当前实体或实体配置添加自定义代码,包括:命名空间、继承、类特性、及代码片段。 您还可以对当前实体字段添加自定义代码,目前包括:属性特性。 具体添加方式,请参考 这个小节。 本文内容 本文简单介绍了如何在 SnapDevelop 中使用 过滤器设计 选项卡实现数据过滤。 在 过滤器设计 选项卡中创建过滤器后,如果在 服务与API设计 选项卡中选择生成带有过滤器的API,则对应的过滤器(数据)、服务(接口和业务逻辑) )、控制器(调用方法)将被生成。 本节内容 下图红框内的区域就是过滤器中参数的设置。 过滤器是指根据一组逻辑(过滤条件)和用户输入(参数)对来自数据源(过滤源)的数据进行过滤。 目前参数可选择的数据类型包括基本类型和枚举类型。 参数设置提供 必要 和 只读 选项; 必要 选项表示该参数是必需的,只读 选项表示该参数是固定的,不能修改。 同时参数支持集合类型,在下面的 参数是一个“集合” 中有详细描述。 过滤器设计 选项卡允许您配置以下参数设置: 参数名称:参数的名称。 显示名称:参数的显示名称。 数据类型:参数的数据类型。 默认值:指定数据库列的默认值。 如果插入的行没有该列的值,则将使用默认值。 集合:当选择 集合 选项时,当前参数将转换为集合类型,例如:ICollection
必要:该参数是否为必填。 只读:指定过滤器是否为只读。 如果搜索条件和搜索值都已确定(这意味着最终用户无需输入任何值),则可以将此过滤器设置为只读并为过滤器设置默认值。 例如,要搜索温度为30摄氏度的日期,添加一个名为 Temperature 的参数,将默认值设置为 30,并选择只读选项,然后将 TemperatureC 设置为等于 Temperature 参数: 如果选择 只读,那么只会生成 如果不选择 只读,则会生成 条件定义过滤器的逻辑。 共有三种形式:字段、表达式 和 范围。 多个条件可以用 “且” 或 “或” 连接。 您可以在设计器的右下角预览过滤器语法。 除无键实体外的所有实体都有默认的主键过滤器。 请注意,这是指一个完整的实体。 基类实体和从属实体在某种意义上并不是完整的实体; 它们不能单独使用,只能作为一个完整实体的一部分一起使用; 一个完整的实体必须有字段、过滤器、服务和 API 模块。 默认主键过滤器: 字段过滤器由三部分组成。 第一部分是过滤器字段,它告诉过滤器过滤逻辑在哪里工作; 第二部分是过滤参数,是过滤逻辑的输入; 第三部分是运算符,连接字段和参数。 例如:要根据作者过滤博客,可以这样设计: 第一部分过滤对象,即博客的作者。 在字段列表中,可以选择作者实体的主键字段,也可以选择将作者实体与博客实体关联的外键 AuthorId,如下图两个红框所示。 在第二部分(过滤器参数)中,从过滤器参数列表中选择代表作者 ID 的参数 AuthorID。 在第三部分(运算符)中,选择 “==”,因为它需要过滤等于输入作者 ID 的博客。 代码生成预览 过滤器最终生成实体的内部类并将所有逻辑组合成一个表达式: 表达式过滤器实际上是字段过滤器的体现,但表达式过滤器更加灵活和强大。 例如,要过滤掉所有帖子的星数超过 100 且点赞数超过指定值的博客,可以如下设计: 添加一个名为 Star 的参数,设置数据类型为 Int32,设置默认值 100,选择 只读。 添加参数 Like,数据类型设置为 Int32。 将过滤器类型切换为 表达式,输入下图中的表达式,其中点击可选字段输入 Blog.Star,点击过滤器参数输入 Blog.Filter.Star,Sum 表达式函数是从下图右侧选择的。 代码生成预览 为了演示范围过滤器的用法,这里举一个简单的例子:过滤创建时间不在指定范围内且 Category 为指定值的博客。 如果您只是设计三个过滤逻辑,并用 “且” 或 “或” 连接它们,它不会产生期望的结果。 您需要使用范围过滤器,如下所示: 无论红框中有多少个子逻辑,最终都会以单一条件的形式出现与主逻辑连接。 代码生成预览: 过滤器参数可以是一个集合。 例如:根据指定的多个作者 ID 过滤博客: 代码生成预览 您可以对当前过滤器添加自定义代码,包括:命名空间、继承、类特性、及代码片段。 具体添加方式,请参考 这个小节。 您可以在 服务与 API 设计 选项卡中决定是否生成控制器和服务,包括: 然后,您可以选择 生成所有 API 选项来为所有 API 生成控制器,或者选择某些 API 的 生成 API 来仅为某些 API 生成控制器。 本文内容 本文简单介绍了如何在 SnapDevelop 中添加 CRUD 服务。 服务与 API 设计 选项卡提供默认的 CRUD 服务。 您可以选择 添加基础服务 来添加默认服务,也可以单击 添加服务 来添加自定义服务(常用于添加带有过滤器的服务)。 服务标签分为三种类型:基础、覆盖 和 自定义。 服务与 API 设计 选项卡允许您配置服务的以下设置: 参数设置:列出服务的请求参数。 排序设置:(对于 Get、GetList 和 GetPage)单击 添加排序选项 对数据库中的数据进行排序。 您可以选择字段或输入表达式,然后指定按升序或降序排序。 赋值设置:(对于 Add、AddRange 和 Update)您可以设置字段的值。 您可以选择一个字段或输入一个值或表达式。 返回设置:(对于 Get、GetList 和 GetPage)指定服务的每个响应字段的返回值。 您可以选择一个字段或输入一个值或表达式。 (对于Add、AddRange、Update 和 Delete)列出服务的返回值。 对返回数据进行排序:(对于 GetList 和 GetPage)点击选择要排序的数据源,然后点击 添加排序选项 选择字段或输入表达式对数据进行排序。 描述:服务的描述。 以下部分将引导您完成配置这些设置。 除计算列和非级联关联实体字段外,返回值字段可以修改为相同数据类型的其他字段、表达式或固定值。 例如:每个博客都有一个流行度值,如果博客创建时间超过1个月,则流行度值为0,否则流行度值为当前时间的时间戳与博客创建时间之差乘以 stars 的数值,该字段不作为数据库字段,即不保存到数据库: 以 Get 方法为例: 输入表达式: 代码预览: 本节内容 数据库排序的设置会影响数据库查询返回的数据源的排序规则,排序类型可以是字段或表达式。 例如:按照博客创建时间降序从数据库查询数据: 选择 Blog 实体下的 CreatedDate 字段,并将排序规则设置为 降序。 代码预览: 例如:按照星星数与总点赞数的乘积对博客进行降序排序: 首先点击右侧图标切换到表达式,输入表达式: 代码预览: 返回值排序设置不会影响数据库查询返回的数据源的排序,只会改变最终返回结果集的排序。 返回值排序中的数据源表示实体本身以及实体中关联的实体字段。 每个排序源可以设置多种排序规则。 例如,对结果集的子集进行排序:将博客以及博客中的帖子按创建时间降序排序: 代码预览: 级联查询是在查询主实体时加载依赖实体引用字段的数据。 如果选择 级联查询 选项,则设计器中的字段设置(值、字段、表达式)可用于依赖实体或依赖实体的字段,计算列和非级联关联实体字段除外。 例如查询博客时,级联查询该博客的作者: 代码预览: 级联更新是在更新主体实体的同时更新从属实体。 当选择 级联更新 选项时,生成的代码将添加相应实体的 CUD(创建、更新和删除)操作的逻辑。 例如:更新博客时,修改博客及所有帖子的最后修改日期: 代码预览: 本文内容 本文简要介绍了如何在 SnapDevelop 中配置 API。 服务与 API 设计 选项卡最终将影响控制器层的代码生成。 通过 API 设计器,可以轻松配置 API 请求方式、参数来源、授权等。 只需选择 生成所有 API 即可将所有基础服务公开为 API,或者只为需要公开为 API 的服务选择 生成 API。 API 将自动生成。 当然,您还可以进一步配置 API。 服务与 API 设计 选项卡允许您配置 API 的以下设置: 名称:API 的名称。 方法类型:API 的默认方法类型。 路由模板: API 的路由格式。 参数设置:您可以选择从以下方式获取参数:FromQuery、FromRoute、FromForm、FromBody 或 FromHeader。 FromQuery:绑定查询字符串中的参数。 FromRoute:绑定来自请求路由的参数。 FromForm:绑定请求正文中表单数据的参数。 FromBody:绑定请求体中的参数。 FromHeader:绑定请求头中的参数。 授权设置:在项目属性页中启用授权后,API 将使用此处指定的默认策略(默认为 ASP.NET Core 默认策略)。 您还可以选择以下基本授权策略之一:使用上层策略、使用应用程序默认策略、使用匿名策略 或使用其他自定义策略。 使用上层策略:使用上层策略。 默认情况下不进行授权验证。 如果有引用的类库,则使用父类的默认策略。 使用应用程序默认策略:使用应用程序配置的默认策略。 使用匿名策略:使用匿名访问策略。 匿名访问允许请求无需身份验证即可通过。 在授权过程中,将验证指定策略下的权限设置(用户可能需要单独编码和实现策略)。 描述:API 的描述。 自定义代码:请参考 这个小节。 以下部分将引导您完成配置这些设置。 每个 API 都可以有一个名称。 但需要注意的是,更改 API 的名称会影响 API 的请求路由。 例如,将 代码预览: 每个 API 都可以有一个请求方法。 您可以根据需要更改请求方法,也可以使用默认值。 代码预览: 您可以为所有的 API 设置统一的路由格式。 也可以为某个 API 单独设置路由格式。 参数可以与不同的来源绑定; 这决定了 ASP.NET Core 如何绑定请求参数。 API 设计器提供了五个源(不包括 FromService): FromQuery:从请求查询字符串参数推断 FromRoute:从任何与路由模板中的参数匹配的参数名称推断 FromForm:从 IFormFile 和 IFormFileCollection 类型的参数推断 FromHead:从请求头推断 FromBody:从请求体推断 例如,将 代码预览: SnapDevelop 提供三个级别的授权设置:应用程序级别、控制器级别和 API 级别。 本节内容 应用程序级别的授权在 安全 页面上配置。 控制器级授权在服务与 API 设计器中配置。 API 级别授权在 API 设置页面配置: 您可以选择基础授权策略或添加/选择自定义策略。 基础: 自定义: 您可以点击 新建策略 打开 安全 页面并添加/重命名/删除策略。 如果在 安全 页面没有开启授权,则无法在服务与 API 设计器中设置授权,如下图所示(选项变灰): 您可以点击右侧的问号图标,然后在弹出页面左下角点击 安全设置,跳转到 安全 页面: 选择启用认证和授权(授权的前提是认证通过): 现在我们使用示例来逐步了解这些设置。 示例1: 假设博客实体的所有 API 要求通过身份验证的用户才能访问(即 ASP.NET Core 默认策略),但 示例2: 假设博客实体的 您可以对服务(接口)、服务(实现)、和控制器添加自定义代码,包括:命名空间、继承、类特性、及代码片段。 您还可以对当前服务与API添加自定义代码,包括:方法特性及代码片段。 具体添加方式,请参考 这个小节。 通过单击实体设计器左下角的栏,您可以查看当前实体中使用的所有依赖项、表达式和计算字段。public string Summary { get; set; } = String.Empty;
public ICollection<string> Summary { get; set; } = new List<string>();
可空
必要
主键
.HasKey(x => new { x.Id, x.DateTime });
复合主键
builder
.HasKey(x => new { x.Id, x.Level });
无主键实体
builder
.HasNoKey();
验证
[Required]
[RegularExpression("^(\\+|00)[0-9]{1,4}[ ,-]?[0-9]{4,14}(?:x.+)?$", ErrorMessage = "The Phone format is incorrect")]
数据
[StringLength(11, MinimumLength = 8, ErrorMessage = "Length must be between 8 and 11.")]
[Range(Int32.MinValue, 36, ErrorMessage = "Must be a value from 0 to 36.")]
builder
.Property(x => x.TrialMonths)
.HasPrecision(6, 2);
builder
.Property(x => x.Gender)
.HasConversion<string>();
数据存储
builder
.Ignore(x => x.HireDate);
builder
.Property(x => x.FirstName)
.IsConcurrencyToken()
.HasColumnName("col_fn")
.HasColumnType("string");
关系
关系设置
一对一关系
必需一对一
可选一对一
自引用一对一
具有复合外键的一对一
以外键为主键的一对一
一对多关系
必需一对多
可选一对多
自引用一对多
具有复合外键的一对多
多对多关系
概述
联接实体
基本多对多
单向多对多
自引用多对多
杂项
索引
builder
.HasIndex(x => x.DateTime)
.IsUnique()
.HasDatabaseName("index1");
自定义代码
过滤器设计
概述
参数
get
方法。get
和 set
方法。
条件
默认过滤器
字段过滤器
表达式过滤器
范围过滤器
参数是一个“集合”
自定义代码
服务与API设计
Get
、GetList
、GetPage
、Add
、AddRange
、Update
、Delete
和 DeleteRange
。 您可以点击 添加服务 按钮逐个添加基础 API 和过滤 API,也可以选择 添加基础服务 选项一次性添加所有基础 API。服务
概述
返回值设置
If(((Ticks(Now()) - Ticks(AddMonths(Blog.CreatedDate, 1))) < 0), (Abs(Ticks(Blog.CreatedDate) - Ticks(Now())) * Blog.Stars) , 0)
数据库排序
按字段排序
按表达式结果排序
Sum(Blog.Post.Like) * Blog.Stars
,并将排序规则设置为 降序。返回值排序
级联查询
级联更新
API
概述
API名称
GetListByNoFilter
更改为 GetList
:请求方法
路由模板
参数来源
Update
API的参数来源修改为 FromQuery:授权设置
概述
前提条件
示例
Update
API 要求通过 Admin
策略授权的用户才能访问。 您可以按如下方式指定设置:GetPage
API 允许未经身份验证的用户匿名访问,但 Delete
API 只能由通过身份验证的用户访问。 您可以按如下方式配置设置。GetPage
API:Delete
API:自定义代码
依赖关系/表达式/计算字段概述