为何Entity Framework生成非完全随机的Guid?
我用基础EF Core DbContext写了一段简单代码:
var eintrag = new CachingEintrag { Name = whatever }; await context.CachingEintrag.AddAsync(eintrag); await context.SaveChangesAsync();
实体类定义如下:
[Table("tbl_cache_eintrag")] public partial class CachingEintrag { [Key] [Column("guid", Order = 0)] public Guid Guid { get; set; } [Column("name")] public String Name { get; set; } }
数据库里该表的guid字段设置了默认约束:
ADD CONSTRAINT [DF_cache_eintrag_guid] DEFAULT (NEWID()) FOR [guid]
不管是用C#的Guid.NewGuid()、SQL的NEWID()还是依赖默认约束,生成的都应该是符合Guid Version 4规范的完全随机Guid,但上面代码生成的Guid却是这样的:
6B347B1E-5DDD-414D-A611-08DB7428DC3C E08B85CB-9F16-4931-A612-08DB7428DC3C CB65491E-4EDA-435C-A613-08DB7428DC3C 29748B11-ACAB-4077-A614-08DB7428DC3C 4E9FA891-DF7F-43CD-A615-08DB7428DC3C 6DF8379D-E785-421B-A616-08DB7428DC3C 1A117B51-FC57-48D6-A617-08DB7428DC3C
这些Guid虽然是版本4,但明显不是完全随机的。我试过移除异步代码,结果没变化;用SQL Server Profiler查发现根本没用到默认约束,Guid是代码生成后插入的;而且调试到AddAsync()之前确认过没提前给Guid赋值。这到底是怎么回事?
这是EF Core的默认行为:当实体的主键是Guid类型且未显式配置值生成策略时,EF Core会自动启用ValueGeneratedOnAdd策略,在内存中生成带规律的Guid(本质是针对SQL Server优化的UUID v4变种),而非依赖数据库的默认约束。
具体细节:
- 你的
Guid主键没有标记[DatabaseGenerated(DatabaseGeneratedOption.Identity)]或[DatabaseGenerated(DatabaseGeneratedOption.Computed)],EF Core默认判定该主键需要在应用端生成值。 - EF Core内部使用
SequentialGuidValueGenerator生成Guid,它会让Guid的后8字节保持连续递增——这是为了避免完全随机的Guid插入SQL Server时导致索引频繁分裂,以此提升写入性能。你看到的Guid后半段(08DB7428DC3C起始的部分)就是连续递增的区段,前半段则是随机值。 - 由于EF Core已经在应用端生成了Guid值,插入时会直接携带该值,自然不会触发数据库的默认约束逻辑。
如果想让数据库的默认约束生效,有两种配置方式:
通过DataAnnotations特性配置:给
Guid主键添加[DatabaseGenerated(DatabaseGeneratedOption.Identity)]特性,明确告知EF Core该值由数据库生成:[Key] [Column("guid", Order = 0)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Guid { get; set; }通过Fluent API配置:在DbContext的
OnModelCreating方法中指定值生成策略:protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<CachingEintrag>() .Property(e => e.Guid) .ValueGeneratedOnAdd() .HasDefaultValueSql("NEWID()"); }
配置完成后,EF Core就不会在应用端生成Guid,而是依赖数据库的默认约束生成完全随机的Guid,插入操作也不会主动携带Guid值。
内容的提问来源于stack exchange,提问作者Pflanzen sind gut

