推荐关注「码侠江湖」加星标,时刻不忘江湖事
这是 EF Core 系列的第二篇文章,上一篇文章讲解了 EF Core 的一些基础概念,这一篇文章主要围绕实体属性的配置。
点击上方或后方蓝字,阅读 EF Core 系列合集。
实体配置
配置实体的目的,是为了让实体属性与数据库表字段实现正确的映射。
EF Core 有三种方式来配置实体:按约定、数据注释、Fluent API,下面依次进行阐述。
按约定配置
按约定配置,是指 EF Core 遵循一套关于属性类型和名称的简单规则,并相应地配置数据库。
按约定的配置,可以被数据注释(特性)或 Fluent API 重写。
比如,下面这个示例中:
public class Account
{public Guid AccountId { get; set; }public string Name { get; set; }public int Age { get; set; }
}
EF Core 通过遵循命名规则,来配置 Account
实体类中的主键字段。
如果实体类拥有一个名为 Id
的属性,或一个<类名+Id>
的组合,它就会被作为主键。
如果实体类中有一个复合主键,我们就不能按约定配置了。
当 EF Core 使用按约定的配置时,它会遍历所有的公共属性,并通过它们的名称和类型来映射它们。
示例中,Name
属性是一个可以为 Null
的字段,因为字符串类型的默认值是 Null
。
但 Age
属性不会为 Null
,因为它是一个值类型。
当然,如果你想让 Age
属性,在数据库中可以为 Null
,那需要在类型后加上 「?」 后缀:
public int? Age { get; set; }
数据注释
数据注释的表现形式就是特性,它不仅可以用来配置实体属性,还可以永远验证实体数据是否合法。
我们来替换一下 Account
实体类中的内容:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;namespace ConsoleApp1.Entities
{[Table("Account")]public class Account{[Column("AccountId")]public Guid Id { get; set; }[Required][MaxLength(50, ErrorMessage = "长度必须小于50个字符")]public string Name { get; set; }public int Age { get; set; }}
}
Name
属性的特性,它就是数据注释的一种,来自 System.ComponentModel.DataAnnotations
命名空间,这个命名空间中的属性主要与约束有关。
Required
属性,说明 Name
字段不能为空;MaxLengh
属性,限制了数据库中该列的长度。
Account
类型与 AccountId
属性的特性,也属于数据注释。
不过,它们来自于 System.ComponentModel.DataAnnotations.Schema
命名空间,这个命名空间中的属性主要与数据库配置有关。
默认情况下,实体类映射到数据库中的表名,与上下文类中 DbSet 属性名有关。
比如 DbSet<Account>
,它的属性名是 Accounts,
所以映射到数据库中的表名就是 Accounts
。但是使用了 「Table」 特性就会覆盖这个默认行为。
「Column」 特性,则可以为 EF Core 提供,该属性映射到数据库中的列信息。
如果你想在代码中使用 Account
类的 Id
属性,而不是 AccountId
,而又想让它在数据库中,以 AccountId
字段名表示,那么就需要使用 「Column」 特性。
「Column」 特性中还有其它的一些参数,比如字段的顺序与数据库中的类型等,简单来说,它可以定义属性在数据库中的形式。
Fluent API
Fluent API 是一组方法,这些方法提供了大量的 EF Core 配置选项,用来在上下文类中配置实体。
我们可以在 ApplicationContext
类中,添加这么一段代码:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{modelBuilder.Entity<Account>().ToTable("Account");modelBuilder.Entity<Account>().Property(s => s.Id).HasColumnName("AccountId");modelBuilder.Entity<Account>().Property(s => s.Name).IsRequired().HasMaxLength(50);modelBuilder.Entity<Account>().Property(s => s.Age).IsRequired(false);
}
Fluent API 可以在 OnModelCreating
方法中使用,这段配置与前面的数据注释拥有同样的效果。
Fluent API 的使用,需要在一开始,就选择需要配置的实体,然后通过 Property
方法,指定需要添加约束的属性,其他的方法就很清晰明了了。
OnModelCreating
方法会在 ApplicationContext
类第一次实例化时被调用。也就是在这一刻,所有的三种实体配置方式都会被应用。
由于配置规则非常多,而常用的又并不多,所以更多的配置规则,大家可以通过 EF Core 官方文档去查阅。
配置方式的选择
现在,我们主要来说一说,这三种配置方式, 我们应该怎么选择?
「首先是按约定配置,」这个永远都是我们的首选。
因为,拥有与表名相同的类名、拥有与命名约定相匹配的主键属性名,以及拥有与列相同的名称和类型的属性,是我们的首选。这样不需要我们做太多的工作。
「然后是数据注释」,它不仅可以配置实体,最重要的是可以实现数据验证,如必填或最大长度验证等,我们应该使用数据注释,而不是 Fluent API 方法。
原因在于,我们可以很容易的看到,哪个验证规则与哪个属性有关,因为它就在属性的上方,而且具有语义性。另外,数据注释的验证,还可以应用在 MVC 中的视图页面。
比如在 Account
类中,如果验证失败,还可以配置错误信息。这种方法会让我们的验证代码更简单,更容易维护。
「最后是 Fluent API」 ,它用于以上两种方法以外的情况,比如索引、复合键、关系都应该使用 Fluent API。
对于那些我们无法做到的配置,或者当我们想从实体类中隐藏配置时,也必须使用这种方法。
小结
这篇文章主要讲了实体属性的三种配置方式,下篇文章我们将围绕实体的数据库迁移与种子数据的填充。
更多精彩内容,请关注我▼▼
如果喜欢我的文章,那么
在看和转发是对我最大的支持!
(戳下面蓝字阅读)
ASP.NET 6 中间件系列
查缺补漏系统学习 EF Core 6 系列
推荐关注微信公众号:码侠江湖
觉得不错,点个在看再走哟