Seeding your database
You have a fully functional database now, but it's empty! Let's put some test data in there.
There is a built-in way to do this in EF Core, but I don't use it, and don't know anyone who does:
public class DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>().HasData(
new Employee { Id = 1, Name = "John Doe", Email = "john.doe@example.com" },
new Employee { Id = 2, Name = "Jane Doe", Email = "jane.doe@example.com" }
);
}
}
Wait, what's OnModelCreating
? This is a method that is used to configure the attributes of the entities and their properties.
You can use it to do all kinds of cool stuff, but we'll talk more about that later.
As I mentioned, we won't do this, and will do something that is done a lot in the wild. It's not my favorite way to do it, but it works. Most people just do seeding in the Main
method (e.g. the Program.cs file).
We'll create a static class to hold our seeding logic.
public static class SeedData
{
public static void Seed(IServiceProvider serviceProvider)
{
var context = serviceProvider.GetRequiredService<AppDbContext>();
if (!context.Employees.Any())
{
context.Employees.AddRange(
new Employee
{
FirstName = "John",
LastName = "Doe",
SocialSecurityNumber = "123-45-6789",
Address1 = "123 Main St",
City = "Anytown",
State = "NY",
ZipCode = "12345",
PhoneNumber = "555-123-4567",
Email = "john.doe@example.com",
Benefits = new List<EmployeeBenefits>
{
new EmployeeBenefits { BenefitType = BenefitType.Health, Cost = 100.00m },
new EmployeeBenefits { BenefitType = BenefitType.Dental, Cost = 50.00m }
}
},
new Employee
{
FirstName = "Jane",
LastName = "Smith",
SocialSecurityNumber = "987-65-4321",
Address1 = "456 Elm St",
Address2 = "Apt 2B",
City = "Othertown",
State = "CA",
ZipCode = "98765",
PhoneNumber = "555-987-6543",
Email = "jane.smith@example.com",
Benefits = new List<EmployeeBenefits>
{
new EmployeeBenefits { BenefitType = BenefitType.Health, Cost = 120.00m },
new EmployeeBenefits { BenefitType = BenefitType.Vision, Cost = 30.00m }
}
}
);
context.SaveChanges();
}
}
}
We'll need to call this from Program.cs
like so:
var app = builder.Build();
SeedData.Seed(app.Services);
When we run the app, we get a runtime error: Unhandled exception. System.InvalidOperationException: Cannot resolve scoped service 'AppDbContext' from root provider.
Because DbContext
is registered as a scoped service by default, and we lack a scoped service provider to resolve it. Scope inside of an ASP.NET Core app is typically created when there's an HTTP request, and we don't have one when the app is starting. So we'll just create one and dispose of it after the seeding is complete.
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
SeedData.Seed(services);
}
The app runs and SQLTools confirms we have data!