EF Core对Guid主键默认采用客户端生成策略,即调用Add()时由.NET生成Guid.NewGuid();也可配置数据库端生成(如SQL Server的NEWID())或手动控制(DatabaseGeneratedOption.None);但需避免将Guid直接设为聚集索引以防止索引碎片。

EF Core 对 Guid 主键有原生支持,默认就会按客户端生成方式处理,不需要额外配置就能用,但要真正用好,得清楚几种生成策略的区别和适用场景。
默认客户端生成(最常用)
只要实体类主键属性是 Guid 类型、名字叫 Id 或 实体名+Id(比如 UserId),EF Core 就会自动把它识别为主键,并启用 ValueGeneratedOnAdd() —— 也就是在调用 Add() 时,由 .NET 客户端生成 Guid.NewGuid(),再插入数据库。
- 无需加任何特性或 Fluent API 配置
- 插入前 ID 已确定,适合离线场景或需要提前知道 ID 的逻辑(比如生成 URL、发消息)
- 不依赖数据库连接,高并发安全
数据库端生成(SQL Server / PostgreSQL / MySQL 各有写法)
如果希望数据库负责生成 Guid(比如用 SQL Server 的 NEWID() 或 NEWSEQUENTIALID()),就得在 OnModelCreating 中显式配置:
- SQL Server:用
.HasDefaultValueSql("NEWID()")(随机)或"NEWSEQUENTIALID()"(顺序,减少索引碎片) - PostgreSQL:用
.HasDefaultValueSql("gen_random_uuid()")(需启用pgcrypto扩展) - MySQL:用
.HasDefaultValueSql("uuid()") - 注意:必须搭配
.ValueGeneratedOnAdd(),否则 EF 不会跳过赋值
禁用自动生成(手动控制)
如果你要在代码里完全自己控制 Guid 值(比如从外部系统传入、或复用旧数据),就用这个方式:
- 加特性
[DatabaseGenerated(DatabaseGeneratedOption.None)] - 或者 Fluent API 写
.ValueGeneratedNever() - 之后每次
Add()前必须显式赋值Id = ...,否则会存00000000-...导致重复或约束失败
性能提醒:别把 Guid 当聚集索引
Guid 是 16 字节、无序的,直接设为主键 + 聚集索引会导致严重索引碎片,尤其在高写入场景下:
- SQL Server:避免用
NEWID()+ 聚集主键;可用NEWSEQUENTIALID()缓解,但仍建议非聚集主键 + 单独添加自增列作聚集索引 - MySQL(InnoDB):主键强制聚集,所以不推荐用 Guid 做主键;如必须用,考虑加
id BIGINT AUTO_INCREMENT PRIMARY KEY作聚集索引,Guid 字段单独建唯一非聚集索引 - 所有情况:确保查询常用字段上有合适索引,别只靠主键索引查数据
基本上就这些。选哪种策略,关键看你要不要离线生成、是否在意索引性能、用的是什么数据库——不是越“高级”的方案越好,而是匹配你的实际部署和读写模式。










