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

使用EF Core Code First操作Spanner数据库时遇主键检测异常

问题

使用Entity Framework Core的Code First模式创建Google Cloud Spanner数据库时,调用EnsureCreated方法抛出如下异常:

System.InvalidOperationException: 'No primary key was found in the database for table Table DistributionChannel. Call SpannerModelValidationConnectionProvider.Instance.EnableDatabaseModelValidation(false) to disable model validation if this error is a false positive.'

相关代码如下:

实体类DistributionChannel

public class DistributionChannel
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

上下文SpannerContext

public class SpannerContext : DbContext, IDesignTimeDbContextFactory<SpannerContext>
{
    public SpannerContext()
    {
    }

    public SpannerContext(DbContextOptions options) : base(options)
    {
    }

    public DbSet<DistributionChannel> DistributionChannels { get; set; }

    public SpannerContext CreateDbContext(string[] args)
    {
        var builder = new DbContextOptionsBuilder<SpannerContext>();

        var configBuilder = new ConfigurationBuilder()
            .SetBasePath($"{AppContext.BaseDirectory}/Configurations")
            .AddJsonFile("migrations.json")
            .Build();

        var configuration = configBuilder.GetSpannerConfiguration();

        var databaseName = DatabaseName.FromProjectInstanceDatabase(configuration.ProjectId, configuration.InstanceId, configuration.DatabaseId);
        var dataSource = $"Data Source={databaseName}";

        var connectionString = new SpannerConnectionStringBuilder(dataSource).ConnectionString;

        builder.UseSpanner(connectionString,
            config => { config.CommandTimeout(configuration.Timeout); });

        return new SpannerContext(builder.Options);
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.EnableSensitiveDataLogging();
        base.OnConfiguring(optionsBuilder);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new DistributionChannelConfiguration());
        modelBuilder.AddJsonFields();

    }
}

配置类DistributionChannelConfiguration

internal class DistributionChannelConfiguration : IEntityTypeConfiguration<DistributionChannel>
{
    public void Configure(EntityTypeBuilder<DistributionChannel> entity)
    {
        entity.ToTable("DistributionChannel");
        
        entity.HasKey(x => x.Id);
        entity.Property(e => e.Name)
            .IsRequired()
            .HasMaxLength(255)
            .IsUnicode(false);
    }
}

Startup调用代码

//rest of code 

using var scope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope();
using var context = scope.ServiceProvider.GetRequiredService<SpannerContext>();
context.Database.EnsureCreated();
解决办法

1. 显式指定Guid主键的数据库类型

Spanner没有原生Guid类型,通常用STRING(36)存储Guid值。修改DistributionChannelConfiguration中的主键配置,明确指定列类型:

internal class DistributionChannelConfiguration : IEntityTypeConfiguration<DistributionChannel>
{
    public void Configure(EntityTypeBuilder<DistributionChannel> entity)
    {
        entity.ToTable("DistributionChannel");
        
        entity.HasKey(x => x.Id);
        // 添加主键类型配置
        entity.Property(x => x.Id)
            .HasColumnType("STRING(36)")
            .ValueGeneratedOnAdd(); // 如需自动生成Guid,保留此行
        
        entity.Property(e => e.Name)
            .IsRequired()
            .HasMaxLength(255)
            .IsUnicode(false);
    }
}

2. 临时禁用模型验证(仅用于排查问题)

如果是Spanner元数据同步延迟导致的验证误报,可以临时关闭模型验证,确认表是否实际创建成功:
在上下文的CreateDbContext方法中修改Spanner配置:

builder.UseSpanner(connectionString, config => 
{ 
    config.CommandTimeout(configuration.Timeout);
    // 禁用模型验证
    SpannerModelValidationConnectionProvider.Instance.EnableDatabaseModelValidation(false);
});

注意:此方法仅用于排查,不推荐长期使用,避免跳过真实的模型配置问题。

3. 检查Spanner基础状态

确保Google Cloud Spanner实例和数据库已完成初始化,程序拥有操作Spanner的足够权限,且网络连接正常。

内容的提问来源于stack exchange,提问作者Vinicius Andrade

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:32:20