EF Core 默认会自动识别 Id 或 实体类名 + Id(如
OrderId、
ProductId)的属性作为主键,但你也可以显式配置——最常用、最灵活的方式就是
HasKey。
用 HasKey 配置单主键
在
OnModelCreating中调用
HasKey,传入一个 Lambda 表达式指定主键属性:
modelBuilder.Entity<product>().HasKey(p => p.Id);</product>如果主键字段名不是
Id,比如叫
ProductId,也一样写:
.HasKey(p => p.ProductId)配合
ValueGeneratedOnAdd()可启用自增(适用于 SQL Server、MySQL 等支持 Identity 的数据库):
modelBuilder.Entity<product>().Property(p => p.Id).ValueGeneratedOnAdd();</product>
用 HasKey 配置复合主键
复合主键必须用 Fluent API(数据注解不支持),语法是传入匿名类型:
modelBuilder.Entity<orderitem>().HasKey(oi => new { oi.OrderId, oi.ProductId });</orderitem>
这会在数据库中创建由两个字段组成的联合主键约束
注意:EF Core 会自动把这两个字段都设为非空(NOT NULL),且默认不加自增
不建议在大表(如超百万行)上长期使用复合主键,索引维护开销会上升
主键命名与数据库映射细节
HasKey 只负责定义“哪个字段/哪些字段是主键”,不控制列名或是否自增。列名需额外用
HasColumnName,自增行为要配
ValueGeneratedOnAdd或数据注解: 改列名:
.Property(p => p.Id).HasColumnName("product_id")
标记自增(数据注解方式):[Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; }
主键类型支持 int、
long、
Guid,甚至
string(但 string 主键无法自增,需手动赋值)
常见误区提醒
有些情况看似像主键配置,其实属于其他环节:
ToTable("xxx") 是配表名,和主键无关
HasOne/WithMany配的是关系,外键字段需单独声明或靠约定推导 如果实体没定义任何主键,EF Core 会报错:“The entity type 'X' requires a primary key to be defined.” 拥有主键是 EF Core 跟踪实体变更的前提,无主键实体只能用
AsNoTracking()查询只读数据
基本上就这些。HasKey 是主键配置的核心入口,搭配 Property 方法可完成绝大多数场景,不需要过度依赖数据注解。
