googleapis / googleapis/dotnet-spanner-entity-framework
Error: "No primary key was found in the database for table Table TestEntities" when using Database Migration to Spanner with EntityFramework
- Dominant language
- C#
- Stars
- 34
- Forks
- 13
- Avg merge
- 4h 39m
- Merged PRs (30d)
- 10
Description
### Description
When using Google.Cloud.EntityFrameworkCore.Spanner with EF Core migrations, creating a table via migrationBuilder.CreateTable(...) results in the error above:
**No primary key was found in the database for table Table TestEntities.
Call SpannerModelValidationConnectionProvider.Instance.EnableDatabaseModelValidation(false)
to disable model validation if this error is a false positive.**
It happens because the model validation starts before migrations are applied and therefore fails.
The only workaround suggested by the error message is disabling database model validation globally:
`SpannerModelValidationConnectionProvider.Instance.EnableDatabaseModelValidation(false);`
This is a significant behavioral change and not acceptable for production use.
### Environment
**EF Core version:** 8.0.22
**Google.Cloud.EntityFrameworkCore.Spanner version:** 3.8.0
**Database:** Google Cloud Spanner
Migrations enabled ✅
### Reproduction steps
Create a new C# Project with EF Core using the Spanner provider
Add the following migration:
20251216161442_InitialCreate.cs
```
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "TestEntities",
columns: table => new
{
Id = table.Column(type: "STRING(36)", nullable: false),
Name = table.Column(type: "STRING", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TestEntities", x => x.Id);
}
);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(name: "TestEntities");
}
}
```
20251216161442_InitialCreate.Designer.cs
```
[DbContext(typeof(TestDbContext))]
[Migration("20251216161442_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.Entity("YOUR_NAMESPACE", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("STRING(36)");
b.Property("Name")
.IsRequired()
.HasColumnType("STRING");
b.HasKey("Id");
b.ToTable("TestEntities");
});
#pragma warning restore 612, 618
}
}
```
```
[DbContext(typeof(TestDbContext))]
partial class TestDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "6.0.16");
modelBuilder.Entity("YOUR_NAMESPACE", b =>
{
b.Property("Id")
.HasColumnType("STRING(36)");
b.Property("Name")
.IsRequired()
.HasColumnType("STRING");
b.HasKey("Id");
b.ToTable("TestEntities");
});
#pragma warning restore 612, 618
}
}
```
```
public class TestDbContext(DbContextOptions options, string connectionString)
: DbContext(options)
{
public virtual DbSet TestEntities { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSpanner(connectionString, options =>
{
options.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
});
}
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity(entity =>
{
entity.HasKey(it => it.Id);
entity.ToTable("TestEntities");
});
base.OnModelCreating(modelBuilder);
}
}
```
Important is to have this property as part of the DBContext. If it's not present, everything works as expected:
```
public virtual DbSet TestEntities { get; set; }
```
Start the application or integration test with SpannerEmulator and apply the migration to Cloud Spanner:
**Expected behavior:**
The generated Spanner table should have a primary key defined
EF Core model validation should succeed
No runtime error should occur
**Actual behavior**
On startup, EF Core throws:
Error Message Appears: No primary key was found in the database for table Table TestEntities. Call SpannerModelValidationConnectionProvider.Instance.EnableDatabaseModelValidation(false) to disable model validation if this error is a false positive.
Setting SpannerModelValidationConnectionProvider.Instance.EnableDatabaseModelValidation(false) fixes the issue but is inacceptable.
Thanks in advance!
Contributor guide
Assessment
This issue has not been assessed yet.