This article will be covering in detail the implementation of Entity Framework Core in ASP.NET Core Web API. We will learn about entity framework core in detail i.e. what, how & why and see how to use it in ASP.NET Core Web API to implement CRUD operations. Though here we will be using entity framework in ASP.NET Core this can be implemented even in .NET Framework for your data persistence. I hope you will join me on this and go through step by step demonstration on implementing entity framework core in ASP.NET Core Web API.
Table of Contents
Introduction to Entity Framework Core
Entity Framework has been around since 2008 which has improved over the years. Entity framework core was introduced for .NET Core based applications. It is an open-source object-relational mapper (ORM) built over ADO.NET and an official data access platform from Microsoft. Entity framework core has been rewritten from scratch to make it lightweight, flexible & achieve better performance.
In the absence of an ORM typically lots of code have to be written to perform CRUD operations with the database. using an ORM like entity framework can reduce the number of lines of code to be written for database interactions. Typical ORM will work on classes & database tables of similar structure but entity framework core implements mappings which makes it a lot more flexible i.e. in case table & class does not match then mappings can be exercised to get from objects to tables.
Entity framework core can work with a wide variety of databases. Microsoft provides rich providers for SQL Server & SQLite and there are many other third-party providers some commercial and some from the community.
How does the entity framework in ASP.NET Core works?
- Define domain classes & configure entity framework DbContext API along with mappings to let entity framework work how this class maps to the database schema.
- Write LINQ to objects to fetch data from the database.
- Based on mappings & database provider configured entity framework will translate queries into SQL that’s understood by the database.
- The query is executed and the object is populated with data.
- Data in objects can be modified, deleted or new records can be added to the list & once done call DbContext.saveChanges from EF API to save data back to the database.
- The entity framework will generate the required SQL statements to save data back to the database.
Should we use Entity Framework Core?
Entity framework can increase developer productivity but still, many developers don’t prefer using it due to the complexity it adds to the data access layer.
Use entity framework when
- There is a one-to-one mapping between fields on-screen and columns in the database tables.
- You need to implement CRUD operation for the screen and business logic is not so complex.
- There are no bulk database operations to be implemented.
- There is no need to bother about the SQL generated for the operation i.e. no SQL tweaking are required for the performance
Code First v/s Database First Approach
Entity Framework provides two approaches for development
- Database First Approach: This is used when you already have a database ready or you have a team of DBAs and take the approach that you will be designing the database first and then the application. Entity framework will create Entities for you from the database. Manual changes to the database can be done and the model can be updated from the database.
- Code First Approach: This is used when there is a team of developers who need full control over the code. The entity framework will generate database tables for you based on the domain classes. Here database is just storage with no business logic in the database layer. Any manual changes to the database will be lost.
Implement Entity Framework Core in ASP.NET Core Web API
Demonstration video
Create a project for demonstration
For demonstration purposes, we will be creating an ASP.NET Core 3.1 API Project using Visual Studio 2019 Community Edition. We will be using the code-first approach for the demonstration.
Create the data model
Create an Employee entity class. Here Id will become the primary key column for the database table that will be created for this class. Entity framework interprets property named as Id or ID as the primary key
public class Employee { public int Id { get; set; } public string FirstName { get; set; } public string MiddleName { get; set; } public string LastName { get; set; } public string Designation { get; set; } public double Salary { get; set; } }
Install Entity Framework Core Packages
We need to install the required entity framework packages. You run the below mentioned commands in Package Manager or install required Nuget packages from Nuget Package Manager.
Install-Package Microsoft.EntityFrameworkCore Install-Package Microsoft.EntityFrameworkCore.Design Install-Package Microsoft.EntityFrameworkCore.SqlServer Install-Package Microsoft.EntityFrameworkCore.Tools
Adding database context class
This is the main class that coordinates Entity Framework functionality for a given model class. You need to derive the class from the entity framework DbContext class and specify the entities included in the data model. This class creates a DbSet property for the Employee entity set. An entity set typically represents a database table and an entity represents a row in the table.
The database table will have the same name as the DbSet property name.
public interface IApplicationDbContext { DbSet<Employee> Employees { get; set; } Task<int> SaveChanges(); }
public class ApplicationDbContext : DbContext, IApplicationDbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<Employee> Employees { get; set; } public new async Task<int> SaveChanges() { return await base.SaveChangesAsync(); } }
Connect application to the database
Specify the SQL Server connection string in the appsettings.json file. We are using localdb database which is a lightweight version of the SQL Server Express database engine.
{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=EFCoreDb;Trusted_Connection=True;MultipleActiveResultSets=true" } }
Register database context for dependency injection in Startup class
You need to configure the database context as a service in configureservices in the startup.cs file so that you pass this service to the controller through the constructor parameter.
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"), ef => ef.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName))); services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>()); services.AddControllers(); } //Remaining code has been removed
For more details on Dependency Injection, you can read my another article – https://procodeguide.com/programming/dependency-injection-in-asp-net-core-3/
Add Migrations
To automate the migrations from the entity framework class we need to run the command add-migration in the package manager console.
add-migration FirstMigration
This will add the migration folder & required migration files to the solution as shown below. These files will be on the basis of entities we configured.
To create a database from the migration created above we need to command update-database in the package manager console
update-database
The database as shown below will be created based on entities configured. Here it has created an Employee table based on the Employee model configured.
Add CRUD operations in Repository for Employee
The repository is a component that encapsulated the objects related to the data storage and operations performed over them. You can even write a generic repository but for demonstration purposes, I have added a repository-specific to Employee entity. The interface will contain the operations that are possible (based on requirements) on the entity i.e. CRUD operations. DbContext is passed as a parameter in the constructor using dependency injection. Here we have added the following operations.
- Create – to add a new employee
- GetAll – to get a list of all employees
- GetById – to get particular employee by Id
- Update – to modify existing employee
- Delete – to delete existing employee
public interface IEmployeeRepository { Task<int> Create(Employee employee); Task<List<Employee>> GetAll(); Task<Employee> GetById(int id); Task<string> Update(int id, Employee employee); Task<string> Delete(int id); }
public class EmployeeRepository : IEmployeeRepository { private IApplicationDbContext _dbcontext; public EmployeeRepository(IApplicationDbContext dbcontext) { _dbcontext = dbcontext; } public async Task<int> Create(Employee employee) { _dbcontext.Employees.Add(employee); await _dbcontext.SaveChanges(); return employee.Id; } public async Task<List<Employee>> GetAll() { var employees = await _dbcontext.Employees.ToListAsync<Employee>(); return employees; } public async Task<Employee> GetById(int id) { var employee = await _dbcontext.Employees.Where(empid => empid.Id == id).FirstOrDefaultAsync(); return employee; } public async Task<string> Update(int id, Employee employee) { var employeeupt = await _dbcontext.Employees.Where(empid => empid.Id == id).FirstOrDefaultAsync(); if (employeeupt == null) return "Employee does not exists"; employeeupt.Designation = employee.Designation; employeeupt.Salary = employee.Salary; await _dbcontext.SaveChanges(); return "Employee details successfully modified"; } public async Task<string> Delete(int id) { var employeedel = _dbcontext.Employees.Where(empid => empid.Id == id).FirstOrDefault(); if (employeedel == null) return "Employee does not exists"; _dbcontext.Employees.Remove(employeedel); await _dbcontext.SaveChanges(); return "Employee details deleted modified"; } }
As shown below register Employee repository as a service in the ConfigureServices method of Startup class
services.AddTransient<IEmployeeRepository, EmployeeRepository>();
Repository helps in better testing of the code. Since the repository is passed as a service till the database is ready we can create a dummy repository service for simulation of CRUD operations. Also, we can pass different repository implementations based on environments. If you want to read more about how to handle multiple environments you can read my other article on Configuring multiple ASP.NET Core hosting environment
Add Employee controller
Here is the code for the Employee controller which has been added to expose the CRUD operations for the Employee entity as an API. Employee Repository has been passed as constructor parameter using dependency injection. Implementation has been added by calling the methods in the repository class. I have not covered validations here but before calling the repository method input should be validated.
[Route("api/[controller]")] [ApiController] public class EmployeeController : ControllerBase { private IEmployeeRepository _employeerepository; public EmployeeController(IEmployeeRepository employeerepository) { _employeerepository = employeerepository; } [HttpPost] [Route("Create")] public async Task<ActionResult> create([FromBody] Employee employee) { int empid = await _employeerepository.Create(employee); return Ok(empid); } [HttpGet] [Route("GetAll")] public async Task<ActionResult> GetAll() { var employees = await _employeerepository.GetAll(); return Ok(employees); } [HttpGet] [Route("GetById/{id}")] public async Task<ActionResult> GetById(int id) { var employee = await _employeerepository.GetById(id); return Ok(employee); } [HttpPut] [Route("Update/{id}")] public async Task<IActionResult> Update(int id, Employee employee) { string resp = await _employeerepository.Update(id, employee); return Ok(resp); } [HttpDelete] [Route("Delete/{id}")] public async Task<IActionResult> Delete(int id) { var resp = await _employeerepository.Delete(id); return Ok(resp); } }
Let’s run & test the code
Will be using postman to test the code.
Create – request & response. Here we can see that we are sending a post HTTP request for creating along with Employee object in the body in JSON format & in response we get employee Id
GetAll – request & response. Here we are sending a get HTTP request without any parameters & in response, we get all the employees present in the database.
Entity Framework Conventions
We saw that we just added the entity class for Employee and the table was created for this entity without specifying any metadata for the database or table. This is due to the fact that the entity framework does this based on the default conventions or assumptions it follows.
- DbSet property name is used for table name.
- Entity class property name is used for column name.
- Entity class properties with name ID or classnameID are assumed as primary key.
You can override these conventions by specifying your own details for the table name, column name, primary key, and foreign key details.
Modifying the database with Annotations
Entity class can be modified to specify the metadata for the table being created for entity i.e. it will override the default conventions used for migrations. Data Annotations Attributed available in namespace “System.ComponentModel.DataAnnotations” to specify the column properties for table.
public class Employee { public int Id { get; set; } [Required] [StringLength(60)] public string FirstName { get; set; } [StringLength(60)] public string MiddleName { get; set; } [StringLength(60)] public string LastName { get; set; } [Required] public string Designation { get; set; } [Required] public double Salary { get; set; } }
Entity Framework Fluent API can also be used to configure DbContext classes to override conventions.
Summary
In this article, we learned about how to implement Entity Framework Core in ASP.NET Core Web API with the code-first approach. I have even posted a short video of the implementation.
One thing you should always keep in mind is that the entity framework doesn’t fit in all the scenarios so please do your research well before deciding to implement it in your project.
References – https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-3.1
Source code download
Here you can download the entire source code demonstrated in this article for Entity Framework in ASP.NET Core
https://github.com/procodeguide/EFCore.Sample
What is the entity framework core?
It is an open-source object-relational mapper (ORM) built over ADO.NET and an official data access platform from Microsoft.
Which databases are supported with the Entity framework?
Entity framework core can work with a wide variety of databases. Microsoft provides rich providers for SQL Server & SQLite and there are many other third-party providers some commercial and some from the community.
Is entity framework code asynchronous?
Asynchronous programming is the default mode for ASP.NET Core and Entity Framework Core.