EF Core: "The Database Is Already Up to Date"
You added a migration. Update-Database runs clean and says there's nothing to apply. The table it was supposed to create still isn't there. EF Core isn't wrong about what it did — it's wrong about what the database already has, and that's a different, more specific bug than "my migration is broken."
// what EF Core is actually trusting
// cause 1 — EnsureCreated() and Migrate() don't agree on the rules
context.Database.EnsureCreated() builds your entire schema directly from the current model — fast, convenient, common in test setups and early prototypes. What it does not do is write anything to __EFMigrationsHistory, because it isn't using migrations at all; it's a completely separate code path. Call it once — even in a test project, even years ago, even by a different developer — and you get a real, fully-formed schema that EF's migration system has no record of.
context.Database.EnsureCreated(); // seeds a working database for local dev/testsAdd-Migration AddCustomerEmail Update-Database
Msg 2714, Level 16, State 6, Line 1 There is already an object named 'Customers' in the database.
__EFMigrationsHistory is empty, so EF Core believes no migration has ever run -- including the very first one, which creates the Customers table. It tries to run that first migration now, against a database where Customers already exists from EnsureCreated(), and SQL Server refuses.
INSERT INTO __EFMigrationsHistory (MigrationId, ProductVersion) VALUES ('20260101000000_InitialCreate', '9.0.0'); -- tells EF Core that migration already ran, so it stops trying to recreate Customers -- and moves straight to applying AddCustomerEmail, the one that's actually missing
__EFMigrationsHistory gets partially or manually seeded, EF Core believes every migration already ran, reports "up to date," and the column you just added in a new migration never gets applied at all — same root mismatch, opposite symptom.// cause 2 — a migration file with no matching .Designer.cs
Every migration is actually two files: <Timestamp>_MigrationName.cs (the Up()/Down() methods) and <Timestamp>_MigrationName.Designer.cs (a snapshot of the model at that point, which is how EF Core identifies the migration at all). If the .Designer.cs file is missing — deleted by hand, excluded by an overly broad .gitignore pattern, lost in a merge conflict — EF Core doesn't see a broken migration, it doesn't see a migration at all. It's silently skipped, and everything after it in the sequence gets confused about what's already applied.
Migrations/ ├── 20260101000000_InitialCreate.cs ├── 20260101000000_InitialCreate.Designer.cs ├── 20260201000000_AddCustomerEmail.cs └── (20260201000000_AddCustomerEmail.Designer.cs is missing) ← this migration gets silently skipped
.cs file is clearly in the project, check the Migrations folder for the matching .Designer.cs before anything else — it's a five-second check that rules out this entire cause.// the actual fix, not a workaround
Deleting the migrations folder and starting over "fixes" this by hiding it — the next environment with a different history runs into the same mismatch. The real fix is reconciling __EFMigrationsHistory with reality, and the first step is finding out exactly where the two disagree rather than guessing:
dotnet ef migrations list -- marks each migration [applied] or [pending] based on __EFMigrationsHistory alone -- -- compare that against which tables/columns actually exist to find the exact mismatch
For every migration the list shows as [pending] whose effect is already in the database (the EnsureCreated() case above), insert its row by hand instead of letting EF try to recreate what's already there — using the same pattern shown earlier, with that migration's own ID and a current EF Core version string in place of '20260101000000_InitialCreate' and '9.0.0'.
Once the history table reflects what's genuinely already in the database, Update-Database only applies what's actually missing — which is the entire point of having a history table in the first place.
// if this is part of a .NET 10 migration
Reconciling migrations tends to happen in the same pass as a framework upgrade, and if the database in question is SQLite, .NET 10 also silently changed how Microsoft.Data.Sqlite interprets stored timestamps — worth checking in the same sitting, since it's the same class of bug: code that still runs, just returns something different now. If the model involved uses complex types, EF Core 10 also changed how their columns get named, which is a separate reason a post-upgrade migration can show unexpected renames.
// frequently asked questions
Why does EF Core say the database is already up to date when a migration didn't run?
Update-Database doesn't inspect your schema — it reads the __EFMigrationsHistory table and applies whatever migration isn't listed there. If that table says a migration already ran, EF Core believes it, even when the table or column it was supposed to create was never actually built.
What causes EF Core migrations to get out of sync with the database?
The most common cause is context.Database.EnsureCreated() being called somewhere — it builds the schema directly from the model but never writes to __EFMigrationsHistory, since it's a separate code path from migrations entirely. The second cause is a migration missing its matching .Designer.cs file (deleted by hand, excluded by .gitignore, lost in a merge) — EF Core doesn't see a broken migration, it doesn't see one at all, and silently skips it.
How do I check which EF Core migrations are actually applied?
dotnet ef migrations list marks each migration [applied] or [pending] based on __EFMigrationsHistory alone. Compare that against which tables/columns actually exist in the database to find the exact mismatch.
How do I fix EF Core's migration history table manually?
Insert a row for the migration EF Core doesn't know ran: INSERT INTO __EFMigrationsHistory (MigrationId, ProductVersion) VALUES ('<migration id>', '<ef core version>'). This tells EF Core that migration is already applied, so it stops trying to recreate what already exists and moves on to whatever's genuinely missing.
Why does EnsureCreated() break Update-Database later?
EnsureCreated() builds a fully-formed schema without touching __EFMigrationsHistory. When migrations are introduced later, EF Core believes no migration has ever run — including the first one, which creates tables that already exist from EnsureCreated() — and the database engine refuses with an "already an object named X" error.
Every EF Core migration you've applied gets a row in a table called
__EFMigrationsHistory, right inside your own database.Update-Databasedoesn't inspect your schema to decide what's missing — it reads that table, compares it against the migrations in your project, and applies whatever isn't listed. If that table says a migration already ran, EF Core believes it, even when the table or column that migration was supposed to create was never actually built.