EF Core 中手动配置表名、主键、外键、索引、关系等映射
主要有两种方式:数据注解(特性)和Fluent API。以下是详细说明和示例:
一、表名配置
指定实体对应的数据表名称。
1. 数据注解([Table] 特性)
直接在实体类上标记,指定数据库表名:
using System.ComponentModel.DataAnnotations.Schema;[Table("t_class")] // 实体 Clazz 映射到数据库表 t_class
public class Clazz
{public int Id { get; set; }public string Name { get; set; }
}
2. Fluent API(在 DbContext.OnModelCreating 中配置)
通过
ToTable 方法指定表名:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{modelBuilder.Entity<Clazz>().ToTable("t_class"); // 实体 Clazz 映射到表 t_class
}
二、主键配置
指定实体的主键字段(支持单主键、复合主键)。
1. 数据注解([Key] 特性)
标记单个属性为主键:
public class Emp
{[Key] // 指定 Id 为主键public int EmpId { get; set; }public string Name { get; set; }
}
若需复合主键(多个属性联合作为主键),需用 Fluent API(数据注解不支持复合主键)。
2. Fluent API(HasKey 方法)
单主键:
modelBuilder.Entity<Emp>().HasKey(e => e.EmpId); // 指定 EmpId 为单主键
复合主键(多个属性):
modelBuilder.Entity<Order>().HasKey(o => new { o.OrderId, o.CustomerId }); // OrderId + CustomerId 作为复合主键
三、外键与关系配置
配置实体间的关联(一对一、一对多、多对多)。
1. 数据注解([ForeignKey] 特性)
标记导航属性对应的外键字段:
public class Emp
{public int EmpId { get; set; }public string Name { get; set; }[ForeignKey("Dept")] // 指定 Dept 导航属性对应的外键是 DeptIdpublic int DeptId { get; set; }public Dept Dept { get; set; } // 导航属性:关联到 Dept 实体
}public class Dept
{public int DeptId { get; set; }public string DeptName { get; set; }public List<Emp> Emps { get; set; } // 导航属性:一对多关联 Emp
}
2. Fluent API(HasForeignKey 方法)
modelBuilder.Entity<Emp>().HasOne(e => e.Dept) // Emp 到 Dept 的一对一/多对一关系.WithMany(d => d.Emps) // Dept 到 Emp 的一对多关系.HasForeignKey(e => e.DeptId); // 指定外键为 Emp.DeptId
四、索引配置
为查询频繁的字段创建数据库索引(提升查询性能)。
1. 数据注解([Index] 特性)
public class Emp
{public int EmpId { get; set; }[Index] // 为 Name 字段创建索引public string Name { get; set; }[Index("IX_Emp_DeptId_Name", 1)] // 复合索引:第1个字段是 DeptIdpublic int DeptId { get; set; }[Index("IX_Emp_DeptId_Name", 2)] // 复合索引:第2个字段是 Namepublic string Name { get; set; }
}
2. Fluent API(HasIndex 方法)
// 单字段索引
modelBuilder.Entity<Emp>().HasIndex(e => e.Name);// 复合索引
modelBuilder.Entity<Emp>().HasIndex(e => new { e.DeptId, e.Name }).HasName("IX_Emp_DeptId_Name"); // 自定义索引名
五、其他常用配置
1. 字段非空([Required])
public class Emp
{public int EmpId { get; set; }[Required] // 数据库中 Name 字段不允许为 NULLpublic string Name { get; set; }
}
Fluent API 方式:
modelBuilder.Entity<Emp>().Property(e => e.Name).IsRequired();
2. 字段长度([StringLength])
public class Emp
{public int EmpId { get; set; }[StringLength(50)] // Name 字段长度为 50public string Name { get; set; }
}
Fluent API 方式:
modelBuilder.Entity<Emp>().Property(e => e.Name).HasMaxLength(50);
3. 数据库生成值(自增、默认值)
public class Emp
{[Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)] // 自增主键(数据库自动生成)public int EmpId { get; set; }[DatabaseGenerated(DatabaseGeneratedOption.Computed)] // 数据库计算列(如创建时间默认值)public DateTime CreateTime { get; set; }
}
Fluent API 方式:
modelBuilder.Entity<Emp>().Property(e => e.EmpId).ValueGeneratedOnAdd(); // 自增(等价于 Identity)modelBuilder.Entity<Emp>().Property(e => e.CreateTime).HasDefaultValueSql("GETDATE()"); // 默认值为数据库当前时间
六、总结
配置类型 | 数据注解(特性) | Fluent API(示例) |
表名 | [Table("t_class")] | Entity().ToTable("t_class") |
主键 | [Key] | Entity().HasKey(e => e.EmpId) |
外键 | [ForeignKey("Dept")] | Entity().HasOne(e => e.Dept).WithMany().HasForeignKey(e => e.DeptId) |
索引 | [Index] | Entity().HasIndex(e => e.Name) |
非空 | [Required] | Entity().Property(e => e.Name).IsRequired() |
长度 | [StringLength(50)] | Entity().Property(e => e.Name).HasMaxLength(50) |
自增 / 默认值 | [DatabaseGenerated(...)] | Entity().Property(e => e.EmpId).ValueGeneratedOnAdd() |
通过数据注解(简单直观,适合单实体配置)或Fluent API(灵活强大,适合复杂关系 / 全局配置),可以精准控制 EF Core 与数据库的映射逻辑,适配各种业务场景~
