实体属性Entity Properties

模型中的每个实体类型都具有一组属性,这些属性 EF Core 将从数据库中读取和写入数据。 如果使用关系数据库,实体属性将映射到表列。

包含和排除的属性Included and excluded properties

按照约定,具有 getter 和 setter 的所有公共属性都将包括在模型中。

可以按如下所述排除特定属性:

  1. public class Blog
  2. {
  3. public int BlogId { get; set; }
  4. public string Url { get; set; }
  5. [NotMapped]
  6. public DateTime LoadedFromDatabase { get; set; }
  7. }
  1. protected override void OnModelCreating(ModelBuilder modelBuilder)
  2. {
  3. modelBuilder.Entity<Blog>()
  4. .Ignore(b => b.LoadedFromDatabase);
  5. }

列名Column names

按照约定,使用关系数据库时,实体属性映射到与属性同名的表列。

如果希望使用不同的名称配置列,可以执行以下操作:

  1. public class Blog
  2. {
  3. [Column("blog_id")]
  4. public int BlogId { get; set; }
  5. public string Url { get; set; }
  6. }
  1. protected override void OnModelCreating(ModelBuilder modelBuilder)
  2. {
  3. modelBuilder.Entity<Blog>()
  4. .Property(b => b.BlogId)
  5. .HasColumnName("blog_id");
  6. }

列数据类型Column data types

使用关系数据库时,数据库提供程序根据属性的 .NET 类型选择数据类型。 它还会考虑其他元数据,如配置的最大长度、属性是否是主键的一部分等。

例如,SQL Server 将属性映射到列,将属性映射到 DateTime datetime2(7) string nvarchar(max) 列(对于用作键的属性,则为 nvarchar(450) )。

您还可以配置列,以便为列指定精确的数据类型。 例如,以下代码将配置 Url 为一个非 unicode 字符串,其最大长度为 200Rating 小数位数为,小数 5 位数为,小数位数为 2

  1. public class Blog
  2. {
  3. public int BlogId { get; set; }
  4. [Column(TypeName = "varchar(200)")]
  5. public string Url { get; set; }
  6. [Column(TypeName = "decimal(5, 2)")]
  7. public decimal Rating { get; set; }
  8. }
  1. protected override void OnModelCreating(ModelBuilder modelBuilder)
  2. {
  3. modelBuilder.Entity<Blog>(eb =>
  4. {
  5. eb.Property(b => b.Url).HasColumnType("varchar(200)");
  6. eb.Property(b => b.Rating).HasColumnType("decimal(5, 2)");
  7. });
  8. }

最大长度Maximum length

配置最大长度会向数据库提供程序提供有关要为给定属性选择的相应列数据类型的提示。 最大长度仅适用于数组数据类型,例如 stringbyte[]

备注

在将数据传递给提供程序之前,实体框架不会验证最大长度。 提供程序或数据存储将根据需要进行验证。 例如,如果以 SQL Server 为目标,则超出最大长度将导致异常,因为基础列的数据类型将不允许存储过多的数据。

在下面的示例中,配置最大长度为500将导致 nvarchar(500) 在 SQL Server 上创建类型为的列:

  1. public class Blog
  2. {
  3. public int BlogId { get; set; }
  4. [MaxLength(500)]
  5. public string Url { get; set; }
  6. }
  1. protected override void OnModelCreating(ModelBuilder modelBuilder)
  2. {
  3. modelBuilder.Entity<Blog>()
  4. .Property(b => b.Url)
  5. .HasMaxLength(500);
  6. }

精度和小数位数Precision and Scale

从 EFCore 5.0 开始,可以使用 Fluent API 来配置精度和小数位数。 它告知数据库提供程序所需的存储空间量。 它仅适用于数据类型,在这种情况下,提供程序允许精度和小数位数变化-通常仅限 decimalDateTime

对于 decimal 属性,精度定义表示列将包含的任何值所需的最大位数,而 scale 定义所需的最大小数位数。 对于 DateTime 属性,精度定义表示秒的小数部分所需的最大位数,并且不使用小数位数。

备注

在将数据传递给提供程序之前,实体框架不会进行任何精度验证或缩放。 根据需要验证提供程序或数据存储。 例如,如果以 SQL Server 为目标,则数据类型为的列 datetime 不允许设置精度,而一个列的 datetime2 精度介于0到7(含)之间。

在下面的示例中, Score 将属性配置为具有精度14和小数位数2将导致 decimal(14,2) 在 SQL Server 上创建类型为的列,并且 LastUpdated 将属性配置为具有精度3将导致类型为的列 datetime2(3)

  1. protected override void OnModelCreating(ModelBuilder modelBuilder)
  2. {
  3. modelBuilder.Entity<Blog>()
  4. .Property(b => b.Score)
  5. .HasPrecision(14, 2);
  6. modelBuilder.Entity<Blog>()
  7. .Property(b => b.LastUpdated)
  8. .HasPrecision(3);
  9. }

备注

永远不会定义规模,无需先定义精度,因此用于定义刻度的流畅 API 是 HasPrecision(precision, scale)

必需属性和可选属性Required and optional properties

如果属性对于包含有效,则将其视为可选 null 。 如果 null 不是要分配给属性的有效值,则将其视为必需属性。 映射到关系数据库架构时,必需的属性将创建为不可为 null 的列,而可选属性则创建为可以为 null 的列。

约定Conventions

按照约定,.NET 类型可以包含 null 的属性将配置为可选,而 .NET 类型不能包含 null 的属性将根据需要进行配置。 例如,具有 .net 值类型( intdecimal 、等)的所有属性 bool 都是必需的,并且具有可为 null 的 .net 值类型(、、等)的所有属性 int? decimal? bool? 都配置为可选。

C # 8 引入了一个名为 null 的引用类型的新功能,该功能允许对引用类型进行批注,以指示它是否可用于包含空值。 此功能在默认情况下处于禁用状态,如果启用,它将按以下方式修改 EF Core 的行为:

  • 如果禁用可为 null 的引用类型(默认值),则所有具有 .NET 引用类型的属性都将按约定配置为可选(例如 string )。
  • 如果启用了可以为 null 的引用类型,则将根据 .NET 类型的 c # 为空性配置属性: string? 将配置为可选,而 string 将配置为 “必需”。

下面的示例显示了一个具有必需和可选属性的实体类型,禁用了可为 null 的引用功能(默认值),并启用了该功能:

  1. public class CustomerWithoutNullableReferenceTypes
  2. {
  3. public int Id { get; set; }
  4. [Required] // Data annotations needed to configure as required
  5. public string FirstName { get; set; }
  6. [Required]
  7. public string LastName { get; set; } // Data annotations needed to configure as required
  8. public string MiddleName { get; set; } // Optional by convention
  9. }
  1. public class Customer
  2. {
  3. public int Id { get; set; }
  4. public string FirstName { get; set; } // Required by convention
  5. public string LastName { get; set; } // Required by convention
  6. public string? MiddleName { get; set; } // Optional by convention
  7. public Customer(string firstName, string lastName, string? middleName = null)
  8. {
  9. FirstName = firstName;
  10. LastName = lastName;
  11. MiddleName = middleName;
  12. }
  13. }

建议使用可以为 null 的引用类型,因为它会将 c # 代码中表示的可为 null 性传递到 EF Core 的模型和数据库,并免去使用熟知 API 或数据批注来两次表示相同的概念。

备注

在现有项目上启用可以为 null 的引用类型时要格外小心:现在配置为可选的引用类型属性现在将配置为 “必需”,除非它们显式批注为可为 null。 管理关系数据库架构时,这可能会导致生成更改数据库列的为 null 性的迁移。

有关可以为 null 的引用类型以及如何将其与 EF Core 一起使用的详细信息,请参阅此功能的专用文档页

显式配置Explicit configuration

可以按如下所示将 “约定” 可以为 “可选” 的属性配置为 “必需”:

  1. public class Blog
  2. {
  3. public int BlogId { get; set; }
  4. [Required]
  5. public string Url { get; set; }
  6. }
  1. protected override void OnModelCreating(ModelBuilder modelBuilder)
  2. {
  3. modelBuilder.Entity<Blog>()
  4. .Property(b => b.Url)
  5. .IsRequired();
  6. }

列排序规则Column collations

备注

EF Core 5.0 中已引入了此功能。

可以在文本列上定义排序规则,以确定如何对它们进行比较和排序。 例如,以下示例将 SQL Server 列配置为不区分大小写:

  1. modelBuilder.Entity<Customer>().Property(c => c.Name)
  2. .UseCollation("SQL_Latin1_General_CP1_CI_AS");

如果数据库中的所有列都需要使用特定的排序规则,请改为在数据库级别定义排序规则。

有关排序规则 EF Core 支持的常规信息,请参阅排序规则文档页