EF Core Fluent API:强大而灵活的数据模型配置

EF Core Fluent API:强大而灵活的数据模型配置

【免费下载链接】efcore efcore: 是 .NET 平台上一个开源的对象关系映射(ORM)框架,用于操作关系型数据库。适合开发者使用 .NET 进行数据库操作,简化数据访问和持久化过程。 【免费下载链接】efcore 项目地址: https://gitcode.com/GitHub_Trending/ef/efcore

引言

你是否曾经在使用Entity Framework Core时,为了精确控制数据库映射而苦恼?是否觉得数据注解(Data Annotations)在某些复杂场景下力不从心?EF Core Fluent API正是为了解决这些问题而设计的强大工具。它提供了比数据注解更丰富、更灵活的配置选项,让你能够完全掌控实体模型与数据库之间的映射关系。

通过本文,你将掌握:

  • Fluent API的核心概念和优势
  • 实体、属性和关系的完整配置方法
  • 高级配置技巧和最佳实践
  • 实际应用场景和代码示例

Fluent API 概述

什么是Fluent API?

Fluent API(流畅接口)是EF Core中用于配置数据模型的一种编程方式。它采用链式方法调用的设计模式,让配置代码更加清晰、易读。与数据注解相比,Fluent API提供了更细粒度的控制能力。

为什么选择Fluent API?

mermaid

核心配置方法详解

1. 实体配置

基本实体配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // 配置实体映射的表名
    modelBuilder.Entity<Blog>().ToTable("Blogs");
    
    // 配置架构
    modelBuilder.Entity<Blog>().ToTable("Blogs", "blogging");
    
    // 排除实体
    modelBuilder.Ignore<BlogMetadata>();
}
主键配置
modelBuilder.Entity<Order>()
    .HasKey(o => o.OrderId);  // 单字段主键

modelBuilder.Entity<OrderDetail>()
    .HasKey(od => new { od.OrderId, od.ProductId });  // 复合主键

modelBuilder.Entity<ViewOnlyEntity>()
    .HasNoKey();  // 无主键实体(仅用于查询)

2. 属性配置

基本属性配置
modelBuilder.Entity<Blog>()
    .Property(b => b.Url)
    .IsRequired()                  // 非空约束
    .HasMaxLength(500)             // 最大长度
    .HasColumnName("BlogUrl")      // 列名映射
    .HasDefaultValue("https://")   // 默认值
    .HasComment("博客链接地址");    // 列注释
数据类型和转换器
// 配置数据类型
modelBuilder.Entity<Product>()
    .Property(p => p.Price)
    .HasColumnType("decimal(18,2)");

// 使用值转换器
modelBuilder.Entity<Blog>()
    .Property(b => b.Status)
    .HasConversion(
        v => v.ToString(),
        v => (BlogStatus)Enum.Parse(typeof(BlogStatus), v)
    );
计算列和默认值
modelBuilder.Entity<Order>()
    .Property(o => o.CreatedDate)
    .HasDefaultValueSql("GETDATE()");  // SQL Server默认值

modelBuilder.Entity<Order>()
    .Property(o => o.TotalAmount)
    .HasComputedColumnSql("[Quantity] * [UnitPrice]");  // 计算列

3. 关系配置

一对一关系
modelBuilder.Entity<Blog>()
    .HasOne(b => b.BlogImage)
    .WithOne(i => i.Blog)
    .HasForeignKey<BlogImage>(i => i.BlogId);
一对多关系
modelBuilder.Entity<Blog>()
    .HasMany(b => b.Posts)
    .WithOne(p => p.Blog)
    .HasForeignKey(p => p.BlogId)
    .OnDelete(DeleteBehavior.Cascade);  // 级联删除
多对多关系
modelBuilder.Entity<Post>()
    .HasMany(p => p.Tags)
    .WithMany(t => t.Posts)
    .UsingEntity<PostTag>(
        j => j.HasOne(pt => pt.Tag).WithMany().HasForeignKey(pt => pt.TagId),
        j => j.HasOne(pt => pt.Post).WithMany().HasForeignKey(pt => pt.PostId),
        j => j.HasKey(pt => new { pt.PostId, pt.TagId })
    );

4. 索引配置

// 创建唯一索引
modelBuilder.Entity<User>()
    .HasIndex(u => u.Email)
    .IsUnique();

// 复合索引
modelBuilder.Entity<Post>()
    .HasIndex(p => new { p.BlogId, p.CreatedDate })
    .IsDescending(false, true);  // BlogId升序,CreatedDate降序

// 包含列索引(SQL Server)
modelBuilder.Entity<Post>()
    .HasIndex(p => p.Title)
    .IncludeProperties(p => new { p.Content, p.AuthorId });

高级配置技巧

1. 继承映射策略

// TPH(Table Per Hierarchy)策略
modelBuilder.Entity<Blog>()
    .HasDiscriminator<string>("BlogType")
    .HasValue<TechnicalBlog>("Technical")
    .HasValue<PersonalBlog>("Personal");

// TPT(Table Per Type)策略  
modelBuilder.Entity<TechnicalBlog>().ToTable("TechnicalBlogs");
modelBuilder.Entity<PersonalBlog>().ToTable("PersonalBlogs");

// TPC(Table Per Concrete)策略
modelBuilder.Entity<TechnicalBlog>().UseTpcMappingStrategy();
modelBuilder.Entity<PersonalBlog>().UseTpcMappingStrategy();

2. 复杂类型配置

modelBuilder.Entity<Order>()
    .OwnsOne(o => o.ShippingAddress, address =>
    {
        address.Property(a => a.Street).HasMaxLength(100);
        address.Property(a => a.City).HasMaxLength(50);
        address.Property(a => a.ZipCode).HasMaxLength(10);
    });

modelBuilder.Entity<Customer>()
    .OwnsMany(c => c.Addresses, address =>
    {
        address.WithOwner().HasForeignKey("CustomerId");
        address.Property<int>("Id");
        address.HasKey("Id");
    });

3. 全局配置

// 配置默认架构
modelBuilder.HasDefaultSchema("sales");

// 配置全局查询过滤器
modelBuilder.Entity<Blog>()
    .HasQueryFilter(b => !b.IsDeleted);

// 配置并发令牌
modelBuilder.Entity<Blog>()
    .Property(b => b.Timestamp)
    .IsRowVersion();

配置的组织和管理

使用 IEntityTypeConfiguration

public class BlogConfiguration : IEntityTypeConfiguration<Blog>
{
    public void Configure(EntityTypeBuilder<Blog> builder)
    {
        builder.ToTable("Blogs");
        builder.HasKey(b => b.BlogId);
        builder.Property(b => b.Url).HasMaxLength(500);
        builder.HasMany(b => b.Posts).WithOne(p => p.Blog);
    }
}

// 在DbContext中应用配置
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfiguration(new BlogConfiguration());
}

自动应用所有配置

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfigurationsFromAssembly(
        typeof(ApplicationDbContext).Assembly);
}

实际应用场景

场景1:电子商务系统

// 产品实体配置
modelBuilder.Entity<Product>(entity =>
{
    entity.ToTable("Products", "catalog");
    entity.HasKey(p => p.ProductId);
    
    entity.Property(p => p.Name)
        .HasMaxLength(200)
        .IsRequired();
    
    entity.Property(p => p.Price)
        .HasColumnType("decimal(18,2)")
        .HasDefaultValue(0);
    
    entity.HasIndex(p => p.CategoryId);
    entity.HasIndex(p => new { p.Name, p.BrandId });
});

// 订单实体配置
modelBuilder.Entity<Order>(entity =>
{
    entity.ToTable("Orders", "sales");
    entity.HasKey(o => o.OrderId);
    
    entity.Property(o => o.OrderDate)
        .HasDefaultValueSql("GETDATE()");
    
    entity.Property(o => o.TotalAmount)
        .HasComputedColumnSql("[SubTotal] + [TaxAmount] - [DiscountAmount]");
    
    entity.HasMany(o => o.OrderItems)
        .WithOne(oi => oi.Order)
        .OnDelete(DeleteBehavior.Cascade);
});

场景2:博客系统

// 博客文章配置
modelBuilder.Entity<Post>(entity =>
{
    entity.HasKey(p => p.PostId);
    
    entity.Property(p => p.Title)
        .HasMaxLength(200)
        .IsRequired();
    
    entity.Property(p => p.Slug)
        .HasMaxLength(250)
        .IsRequired();
    
    entity.HasIndex(p => p.Slug)
        .IsUnique();
    
    entity.HasIndex(p => new { p.BlogId, p.PublishDate })
        .IsDescending(false, true);
    
    // 软删除支持
    entity.HasQueryFilter(p => !p.IsDeleted);
});

// 标签配置
modelBuilder.Entity<Tag>(entity =>
{
    entity.HasKey(t => t.TagId);
    
    entity.Property(t => t.Name)
        .HasMaxLength(50)
        .IsRequired();
    
    entity.HasIndex(t => t.Name)
        .IsUnique();
    
    // 多对多关系
    entity.HasMany(t => t.Posts)
        .WithMany(p => p.Tags)
        .UsingEntity<PostTag>(
            j => j.HasOne(pt => pt.Post).WithMany().HasForeignKey(pt => pt.PostId),
            j => j.HasOne(pt => pt.Tag).WithMany().HasForeignKey(pt => pt.TagId),
            j => j.HasKey(pt => new { pt.PostId, pt.TagId })
        );
});

【免费下载链接】efcore efcore: 是 .NET 平台上一个开源的对象关系映射(ORM)框架,用于操作关系型数据库。适合开发者使用 .NET 进行数据库操作,简化数据访问和持久化过程。 【免费下载链接】efcore 项目地址: https://gitcode.com/GitHub_Trending/ef/efcore

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值