三、EFCore系列之Fluent API

一、在数据库上下文类中配置

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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值