While working with the EF Core Code-First approach, we create the classes for our domain entities first. Later, we’ll create the database from our code by using migrations. This is the opposite of the Database-First approach where we design our database first and then create the classes which match our database design.

In the EF Core Code-First approach, we have full control over the code and the database is just a store without any logic. This approach is helpful in situations where we are starting with the development of a new project and we don’t have a clear picture of how our database should look like yet.

We don’t have to worry about creating and updating the database. We can just make the changes in our code and then sync everything easily with the database. The important thing to note is that the manual changes that we make to the database could be lost during migration. So we should make changes to the code only.

Source code for this blog post can be found on this Github repo.

Let’s have a look at how to create a .NET Core Web API application with EF Core Code-First approach.

The article is divided into the following sections:

Setting Up the ASP.NET Core Web API Project

As a first step, let’s set up an ASP.NET Core Web API Project. We have explained this in detail in one of our other articles: Creating and configuring a new ASP.NET Core Web API project

The article linked above covers a lot of additional topics. You may go through the entire article if you want to, but the section linked above is quite enough to follow along with this article.

Following the article linked above, let’s create a new project called EFCoreCodeFirstSample

Configuring EF Core

Once we have set up the project, the next step is to set up the EF Core.

Following are the steps for configuring the EF Core:

Defining the Model

First, let’s define the model. We will start by creating a folderModels within the root of the application.

Let’s add a new class Employee.cs inside:

The code above defines the classEmployee with some properties. Additionally, we have decorated the EmployeeId property with Key and DatabaseGenerated attributes. We did this because we will be converting this class into a database table and the columnEmployeeId will serve as our primary key with the auto-incremented identity.

Creating a Context File

As the next step, let’s create a context class, define database connection and register the context. The process is explained in detail in one of our other articles: Context Class and the Database Connection

Following the above article, let’s define the context file EmployeeContext.cs:

and let’s define the database connection in the appsettings.json file as:

Of course, modify the ConnectionStringproperty to match with that of ours.

Then let’s register our context in the Startup.cs

Generating the Database from Code Using Migrations

Our next step is to add Code-First Migrations. Migrations automate the creation of database based on our Model. The EF Core packages required for migration will be added with .NET Core project setup.

Run the following command in the Package Manager console:

PM> Add-Migration EFCoreCodeFirstSample.Models.EmployeeContext

This will create the classes for supporting migrations.

Migration classes

Now let’s apply those changes to the database.

Run the following command:

PM> update-database

This will update the database based on our models.

Now let’s verify that the database and tables are created by opening SQL Server Management Studio or Visual Studio Server Explorer:

Database after migration

We can see the database EmployeeDBis created with a table Employeeswhich contains the columns based on the fields we defined in our model.

Each time we make changes to our entities and do a migration, we can see new migration files created in our solution and new entries in the table__EFMigrationsHistory.

When using EF Core Code-First approach the best practice is to make all modifications to the database through the model and then update the database by doing the migration. Ideally, we should not make any manual changes to the database.

With that, EF Core setup is complete.

Seeding Data, Reverting Migrations and Creating DB Scripts

Seeding Data

Data seeding allows us to provide initial data during the creation of a database. Then, EF Core migrations will automatically determine what insert, update or delete operations need to be applied when upgrading the database to a new version of the model.

So let’s create some seed data now. For this, we need to override the OnModelCreating method in the EmployeeContext class:

Here we have provided two Employee records which will be inserted into the database as part of the migration.

Let’s run the migration commands once again:

Add-Migration EFCoreCodeFirstSample.Models.EmployeeContextSeed

update-database

This will create a new migration file in our Migrations folder and update the database with the seed data we provided:

Now the Employee table in our database will look like this:

Employee table after seeding

Reverting Migrations

After making changes to our EF Core model, the database schema will be out of sync. To bring it to sync with the model, let’s add another migration.

Let’s add a new property Gender in our employee model and then do a migration.

It is a good practice to give meaningful names to the migration like a commit message in a version control system. For example, if we add a new field Gender to the Employee model, We may give a name like AddEmployeeGender.

Add-Migration EFCoreCodeFirstSample.Models.AddEmployeeGender

Sometimes we add a migration and then realize we need to make additional changes to our model before applying it. To remove the last migration, we can use the command:

Remove-Migration

If we already applied a migration (or several migrations) to the database but need to revert it, we can use the same command to apply migrations, but specify the name of the migration we want to roll back to.

Let’s say we already applied the migration to add Gender column to the database by using below command.

update-database

Now we can see the new column Gender added to the Employee table:

Employee table with gender

Now let’s say we want to revert this migration. We can use the same command by specifying the name of the previous migration:

update-database EFCoreCodeFirstSample.Models.EmployeeContextSeed

Once this is executed, we can see that column Gender is removed from the Employee table:

Employee table without gender

Creating DB Scripts

While deploying our migrations to a production database, it’s useful to generate a SQL script. We can further tune the script to match the production database. Also, we can use the script along with various deployment tools.

The command to generate script is:

Script-Migration

Once we apply this command, we can see a SQL script generated with all changes related to our migrations.

Creating the Repository

Now that we have configured the EF Core, we need a mechanism to access the data context from our API. Directly accessing the context methods from the API controller is a bad practice and we should avoid that.

So let’s implement a simple data repository using the repository pattern. We have explained this pattern in detail in one of our other articles: Implementing the repository pattern

Let’s add a new folder under Models and name itRepository. Then let’s create a new interface calledIDataRepository:

We will later inject this interface into our API Controller and API will be communicating with the data context using this interface.

Next, let’s create a concrete class that implements the interfaceIDataRepository. Let’s add a new folder under Models calledDataManager. Then let’s create a new class EmployeeManager:

The classEmployeeManager handles all database operations related to the employee. The purpose of this class is to separate the actual data operations logic from our API Controller.

This class has the following methods for supporting CRUD operations:

GetAll() – Gets all employee records from the database.

Get() – Gets a specific employee record from the database by passing an Id.

Add() – Creates a new employee record in the database.

Update() – Updates a specific employee record in the database.

Delete() – Removes a specific employee record from the database based on the Id.

As a next step, let’s configure the repository using dependency injection. This can be done in the ConfigureServices method in the Startup.cs as below:

Creating the API Controller

Now that our DataManager is all set, let’s create the API Controller and create the endpoints for handling CRUD operations. We have covered this in detail in one of our other articles: Creating a .NET Core Web API Controller

Following the above article, let’s create the EmployeeController class in the Controllersfolder as below:

That’s it. We have successfully created a Web API controller with endpoints for handling CRUD operations.

Testing the API

Now let’s do a quick round of testing around our API endpoints using Postman.

First, let’s create a new Employee using a Post request:

POST request

Next, let’s do a Get request to get all Employees. We can see the new Employee record which was created in the previous request:

GET request

Now, let’s do a Put request to test the update functionality by changing the last name:

PUT Request

Once again let’s do a Get request and verify that the last name has changed:

GET_after_update

Now that we have successfully tested the API endpoints, let’s verify that the changes we made are actually persisted to the database. Let’s open the SQL Server management studio and verify that the record is created in the Employee table:

SQL Results

Conclusion

Well, that’s all for now. In this article, we have learned the following topics.

  • EF Core Code-First approach and when to use it
  • Setting up a .NET Core Web API project with EF Core Code-First approach
  • Creating a database from code by using migrations
  • Setting up a repository to handle communication between API and the data context
  • Create API endpoints for handling CRUD operations and testing them

Hope you enjoyed the article. Happy programming!

If you have enjoyed reading this article and if you would like to receive the notifications about the freshly published .NET Core content we encourage you to subscribe to our blog.