How do you seed data in EF Core?

Entity Framework & EF Core Modelling Basic 1–2 Yrs2–3 Yrs Conceptual 1 min read

Quick Answer

Two approaches: modelBuilder.Entity<T>().HasData(...) puts fixed reference data (roles, countries, statuses) into migrations — applied by database update, kept in sync via generated migrations. Or a custom seeder that runs at startup and does its own “insert if missing” checks — better for data that references other services or needs logic.

For genuinely static reference data — a list of countries, order statuses — I use HasData in OnModelCreating, which bakes the rows into the migration so they're applied and version-controlled. For anything with logic, or that depends on the environment, I write a small seeder class that runs at startup after migrations and does “check if it exists, insert if not” so it's idempotent and safe to run on every boot. I keep sensitive or environment-specific data out of migrations because migrations ship everywhere.

  • HasData — requires fixed primary key values, generates INSERT/UPDATE/DELETE in the next migration when you change the seed. Only for static, small reference data.
  • Custom seeder: a class run from Program.cs after Migrate() — if (!db.Roles.Any()) db.Roles.AddRange(...); await db.SaveChangesAsync();. Make it idempotent so it's safe to run every startup.
  • Don't seed environment-specific or sensitive data through migrations that ship everywhere.