You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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值,插入时会直接携带该值,自然不会触发数据库的默认约束逻辑。

解决办法

如果想让数据库的默认约束生效,有两种配置方式:

  1. 通过DataAnnotations特性配置:给Guid主键添加[DatabaseGenerated(DatabaseGeneratedOption.Identity)]特性,明确告知EF Core该值由数据库生成:

    [Key]
    [Column("guid", Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Guid { get; set; }
    
  2. 通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:52:33