一、在数据库上下文类中配置
1. 配置表名
默认情况下,EF Core 使用DbSet的属性作为数据库表的名称。也通过 Fluent API 来显式指定表名。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>().ToTable("T_Book");
}
2. 主键约定
EF Core 会自动识别名为 Id 或 <EntityName>Id 的属性作为主键。可以通过 Fluent API 配置其他属性为主键显式指定主键。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>().HasKey(b => b.Number);
}
3. 配置列名
默认情况下,EF Core 使用实体类中的属性名称作为数据库表中的列名。可以通过 Fluent API 显式指定列名。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.Property(b => b.Title)
.HasColumnName("BookName");
}
4. 配置数据类型
默认情况下,EF Core 根据 CLR 类型自动选择合适的数据库类型。可以通过 Fluent API 显式指定数据库类型。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.Property(b => b.Title)
.HasColumnType("VARCHAR(100)");
}
5. 配置字段是否必填
可以通过 Fluent API 显式配置属性是否允许为空或必须有值。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.Property(b => b.Title)
.IsRequired(); // 确保 Title 不为空
modelBuilder.Entity<Book>()
.Property(b => b.AuthorName)
.IsRequired(false); // 允许 AuthorName为空
}
6. 配置字符串长度
对于字符串类型的属性,可以显式指定其最大长度。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.Property(b => b.Title)
.HasMaxLength(100); // 设置 Title 的最大长度为 100
}
7. 忽略属性
希望 EF Core 忽略某些属性,不将其映射到数据库中。可以通过 Ignore 方法实现这一点。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.Ignore(b => b.TempField); // 忽略 TempField 属性
}
8. 配置计算列
可以定义一个计算列,其值由其他列的值计算得出。
MySql中:HasComputedColumnSql("Price * Count")
SQL Server中:HasComputedColumnSql("[Price] * [Count]")
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.Property(b => b.SumPrice)
.HasComputedColumnSql("Price * Count");
}
9. 配置唯一约束
可以通过 Fluent API 为属性或组合属性添加唯一约束。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.HasIndex(b => b.Title)
.IsUnique(); // Title 字段必须唯一
}
10. 设置默认值
可以通过 Fluent API 为属性设置默认值。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.Property(b => b.Status)
.HasDefaultValue("Active");
}
11. 配置索引
可以通过 Fluent API 为实体的某个属性或组合属性创建索引。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.HasIndex(b => b.Title)
.IsUnique(); // 创建唯一索引
modelBuilder.Entity<Book>()
.HasIndex(b => new { b.Price, b.Count}); // 创建复合索引
}
12. 全局查询筛选器
全局查询筛选器是在定义实体模型时设置一些条件,这些条件会自动应用到涉及这些实体的所有 LINQ 查询中。这在实现软删除、多租户等场景中特别有用。目前,不能在同一个实体上定义多个独立的查询筛选器,但可以使用逻辑运算符组合多个条件在一个筛选器内。
// 数据库上下文中配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 全局查询筛选器
modelBuilder.HasQueryFilter(b => b.IsDeleted == false);
}
如果需要临时绕过全局查询筛选器,可以在查询时使用 IgnoreQueryFilters() 方法。
private static void GlobalQueryFilter(MyDbContext ctx)
{
// IgnoreQueryFilters() 忽略全局查询筛选器。
var articles = ctx.Articles.IgnoreQueryFilters().ToList();
foreach (var article in articles)
{
Console.WriteLine($"文章标题:{article.Title}");
}
}
二、在实体配置类中配置
使用实体配置类(实现IEntityTypeConfiguration<T>
接口)来集中管理 Fluent API 配置。
首先,在数据库上下文中应用当前程序集中的所有实体配置类。这些配置类实现了IEntityTypeConfiguration<T> 接口,并提供了对特定实体类型的详细配置。
public class MyDbContext : DbContext
{
// DbSet指定 要映射到数据库的实体类
public DbSet<Book> Books { get; set; }
public DbSet<Person> Persons { get; set; }
/// <summary>
/// 配置数据库连接。
/// </summary>
/// <param name="optionsBuilder"></param>
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
// 1. 定义数据库连接字符串
String connectionString = "";
// 2. 指定数据库类型为 MySQL
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
}
/// <summary>
/// 配置实体与数据库表之间的映射关系。
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// 从当前程序集中读取所有的实体配置
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
数据库连接字符串设置详见: 一、EFCore系列之数据迁移_ef core 数据迁移-优快云博客
之后在配置类中进行对实体类的设置。
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
public class BookConfig : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
// 1. 配置表名
builder.ToTable("T_Book");
// 2. 主键约定
builder.HasKey(b => b.Number);
// 3. 配置列名
builder.Property(b => b.Title).HasColumnName("BookName");
// 4. 配置数据类型
builder.Property(b => b.Title).HasColumnType("VARCHAR(100)");
// 5. 配置字段是否必填
builder.Property(b => b.Title).IsRequired(); // 确保 Title 不为空
builder.Property(b => b.AuthorName).IsRequired(false); // 允许 AuthorName 为空
// 6. 配置字符串长度
builder.Property(b => b.Title).HasMaxLength(100); // 设置 Title 的最大长度为 100
// 7. 忽略属性
builder.Ignore(b => b.TempField); // 忽略 TempField 属性
// 8. 配置计算列
builder.Property(b => b.SumPrice).HasComputedColumnSql("[Price] * [Count]"); // 注意 SQL Server 中使用方括号
// 9. 配置唯一约束
builder.HasIndex(b => b.Title).IsUnique(); // Title 字段必须唯一
// 10. 设置默认值
builder.Property(b => b.Status).HasDefaultValue("Active");
// 11. 创建索引
builder.HasIndex(b => b.Title).IsUnique(); // 创建唯一索引
builder.HasIndex(b => new { b.Price, b.Count }); // 创建复合索引
// 12. 全局查询筛选器
builder.HasQueryFilter(b => b.IsDeleted == false);
}
}