Integrating Entity Framework Core in Web App
What is Entity Framework Core?
Entity Framework Core is a lightweight, extensible, open source and cross-platform object-relational mapper (ORM) helping developers to work with databases using .NET objects. This prevents us to write data-access codes and query data using these .NET objects. EF Core supports many database engines. List of engines supported.
The main entity in the EF core is the model.
Model
The model comprises of entities and the context object(a class derived from the DbContext base class). Context object acts as a session to the database and is used to perform operations on the database.
EF core 3.1 implements .NET standard 2.0 which is supported by below set of frameworks i.e. we can use EF core 3.1 against these platforms.
We can generate a database from the model through the use of migration(more about it later). We can evolve our database as the model is changed.
Creating an EF core implementation
We will use an exiting application(here) built with hard-coded in-memory data. The application is based on CRUD operation for restaurants. Step-by-step we will replace the hard-coded data with EF core and Sql Server as the database implementation.
Current structure of the project look like this
EF core works with .NET entities to query the database. So first we will need entities.
Step 1:- Creating the entities
The existing app consists of Restaurant class and Cuisinetype enum in the Models folder. The restaurant class is the entity we will be working with.
Step 2:- Reference the nuget packages
Include the Microsoft.EntityFramework.Core package. This is the base EF core packages.
Once we have the base package, we need to get the package corresponding to the data store that we will be using; in our case it is SQL Server. So, referencing that package as well.
Step 3:- Creating the Context class
The DbContext base class provided by the EF core manages all the change tracking and performs the database interaction tasks like fetching and saving the data. Behind the scenes it generates appropriate SQL to be sent to the database to perform the operations. It also keep track of what changes were performed on a given entity i.e. whether it was removed, added or modified.
Adding a class deriving from the base DbContext class.
We need to define DbSet property for entities so that we can use those wrappers around these entities to interact with the database. The DbSet can map to tables and views. In our case the DbSet<Restaurant> is mapping to the Restaurants table in the database. The property names map to table names in the database.
Step 4:- Creating Migrations
The migrations feature in EF Core helps in incrementally updating the database schema and keep it in sync with the application’s data model while preserving existing data in the database.
Before we create a migration we need a way to tell the DbContext which database provider we are going to use and the connection string that will be used to interact with it.
Declaring the connection string and letting DbContext know that we are using SQL server. This is done in the startup class.
Although i have hard-coded the connection string in the code, it is not a good practice to do so. The connection string contains username and password to connect to database and it should not be part of project(source control). Few places to store it can be an environment variable, the user secret store, or azure key vault(read more)
Now we need to define a custom constructor inside of the RestaurantDbContext.
One last step before we can perform the migration is to get access to all the migration commands. These commands are part of nuget package Microsoft.EntityFrameworkCore.Tools
Now we are ready to perform the migrations. Open Package Manager Console and add a new migration. The command is add-migration and the text after that is the message. In this case this is first migration so initial. We can give any meaningful message.
Once it is complete; a new folder will be generated in the solution called Migrations. This will contain two files one snapshot and other will be named starting with a timestamp and the message that we have.
Snapshot:- This contains information regarding the current state of the model when the migration was performed. The next time we run migration EF core will compare this snapshot with the newer version of the model and then generated the schema changes needed to be done.
The migration file contains the details regarding the schema changes to be done to database.
Step 5:- Running Migration
Once we have generated the migration file, we will go ahead and execute the update-database command. This command will inspect the migration file and generate appropriate SQL to make changes to the database schema. Running update-database in package manager console.
Open the SSMS studio and check if we have the database generated.
We have an additional table called _EFMigrationsHistory. This table keeps track of which migration have been performed against the db.
Interacting with Database using EF core
Now we have the database and all the EF core setup done. We can go ahead and write code to perform CRUD operations against this database. Implementing the IRestaurantRepository interface. We are injecting an instance of RestaurantDbContext here.
Once we have the repository implementation using EF core, we can go ahead and register this as a service with the ASP.NET core.
We have registered the service as a transient implementation; what this means is every time we inject IRestaurantRepository we will get a new instance of RestaurantRepository.
That’s all the change we need to do and the application will now be using the database to store and retrieve data instead of the in-memory implementation for it.
Summary
We discussed the implementation details of replacing an in-memory data with the EF core 3.1. We looked into which nuget packages need to be added, along with that we also saw how to create a migration and update the database using the schema of the model we used. We created the context class through which we can interact with the database without having to write any SQL commands. The translation of the command into SQL queries is taken care by the Entity Framework itself.