Building APIs with C# and ASP.NET Core

Seeding a Database

Spencer Schneidenbach

Spencer Schneidenbach

Aviron Software, Microsoft MVP
Building APIs with C# and ASP.NET Core

Check out a free preview of the full Building APIs with C# and ASP.NET Core course

The "Seeding a Database" Lesson is part of the full, Building APIs with C# and ASP.NET Core course featured in this preview video. Here's what you'd learn in this lesson:

Spencer creates a SeedData class to seed test data in the employees.db database. Because DbContext is registered as a scoped service by default, a temporary scope is created and disposed of after the seeding is complete.

Preview
Close

Transcript from the "Seeding a Database" Lesson

[00:00:00]
>> Spencer Schneidenbach: We have done a lot already. We have connected EF Core to our API, which is awesome, but now we get to seed our database. We get to put stuff in it, okay? We have a fully functional database now. Our database file exists, and we can see it, and we can connect to it inside of EF Core, inside of our ASP.NET Core project.

[00:00:21]
But we wanna put some data in there, right? So let's put in some test data so that we have something to play with. So in EF Core, there is a way to seed your database, but I have not done it, and I don't know anybody else who has, which is you can say that Entity .HasData, and then give it some test data.

[00:00:40]
And the reason that people don't typically do this is that people in a production system, depending on the environment, typically don't want data to go just wantonly inside of a database like this. I should mention as well the OnModelCreating, what the heck is that, it allows you to add some configuration to your entities or even properties on those entities.

[00:01:03]
And we will talk about that a little bit later. But just know for now that it allows you to modify some of the behaviors of the entities that come through Entity Framework Core. It allows you to explicitly modify them, which is really quite useful. Talk more about it later, yes, we will.

[00:01:19]
Okay, I'm not gonna do this, and it's just not something that's done a lot in the wild. I never see anybody use HasData. Typically, what I do see is that they'll just define a class, and then they'll just define a separate class and just do this separately. And they'll do this because they can put it in to their test project and then uncomment it as they need to spin up a database.

[00:01:42]
Or maybe you're moving around a Docker image that has some pre-baked data in it. But we'll go ahead and do this. We're gonna go here, and we're gonna go to our program. I'm gonna go to the Solution Explorer, it's a little bit cleaner looking. We're getting a lot of files up in here.

[00:01:59]
Okay, I'm actually gonna close all these. We did all this, but I do want to open up the project folder for the part that we are on, which is seeding-your-database. Perfect, that's what we need. We'll open up Solution Explorer, and we'll go ahead and add in a class called SeedData.

[00:02:25]
We don't need that definition. We'll just paste ours in. And we're basically just going to go through. From our service provider, we're gonna get a copy of our AppDbContext. And if no employees exist in that context, then we're just gonna add some, and we're gonna add some with some employee benefits.

[00:02:39]
We're gonna add some with some more data than we had previously. So we got John Doe and Jane Smith, pretty good. Okay, so we like to see, we'll create our static class. And then we'll need to call this from Program.cs. So we'll go here. We'll go to Program.cs.

[00:02:58]
And once the app is built, we do have access to the dependency injection pipeline so we can get services from it. So we're gonna call SeedData.Seed. And we're gonna say app.Services.GetRequiredService.
>> Spencer Schneidenbach: AppDbContext, open close, and go. No, actually, it just wants the service provider. We don't even need to do that.

[00:03:27]
So we'll just give it the service provider here, app.Services, and we're gonna run it. And what the heck happened? What's this cannot resolve scoped service AppDbContext? What does that mean from the root provider? We'll break this down a little bit for you. This is a common error, and it's common to encounter and not necessarily fully understand as you're getting into dependency injection.

[00:03:52]
What this is is essentially, there is what's called a root provider. These services that we're adding, we're adding all of those to the root provider. And what it's trying to say, what this method is trying to say in this exception is that DB context, specifically our AppDbContext, is what's called a scoped service.

[00:04:11]
Now, scope kind of is similar to block scope, but it's not a programmatic construct. This is block scope. So we know variables declared here aren't accessible outside of the scope. It's conceptually the same thing, but a scope is typically created in an ASP.NET Core application for the lifetime of an HTTP request.

[00:04:34]
So as a request is executing, the service provider news up what's called a scope or CreateScope right there. So you would say using var scope = CreateScope. I like my using statements with curly braces, so I'm gonna stay with that. And then the HTTP request executes and does stuff.

[00:05:00]
It goes through the middleware pipeline and does things. So in the context of an ASP.NET Core application, that is a scope. And so a context, a single context, once it's requested, is created for the scope of that HTTP request. And after that request is fulfilled and gone, then it gets disposed of.

[00:05:19]
So in this case, our way around this is to simply just create our own scope. And you could do that here if you wanted to, but I'm gonna just do it here instead.
>> Spencer Schneidenbach: .Build, SeedData.Seed, and we're gonna do that.
>> Spencer Schneidenbach: And now you see that it runs successfully.

[00:05:44]
So at this point now, we've set up our seed database, or we've set up our seed method, and we've gotten that data into that database. The next thing we'll do is actually connect our DB context into our API and make it so that we can actually query.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now