How do you seed data in EF Core?
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, generatesINSERT/UPDATE/DELETEin the next migration when you change the seed. Only for static, small reference data.- Custom seeder: a class run from
Program.csafterMigrate()—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.