.NET Zero to Hero Series is now LIVE! JOIN 🚀

13 min read

Entity Framework Core in ASP.NET Core 3.1 - Getting Started


In this article, we will go through Entity Framework Core in ASP.NET Core 3.1 along with its various implementations and concepts. With the ever-growing tech stacks and efficient systems, Rapid Development is crucial for any kind of project. In .NET Core, one of the features that enable rapid development is Entity Framework Core. Since the topic is quite vast, I will split the article into small episodes, so that we get to cover each and every concept. So, let’s get started with the first ‘Episode’ of the Entity Framework Core Series! Here are the topics that I will cover in this part.

What is Entity Framework Core?

However complex or simple your application, it is hard to not notice the vital part that a Database plays in it. I would call a Database / Datasource the heart of any application. So, we will need an efficient way to read and securely write clean data into our data source. You may think of traditional SQL Queries and ADO.NET approaches to achieve the task. While it is still a good option, You are facing the risk of maintainability and speed of development with the traditional SQL approaches.

Entity Framework Core is a lightweight, extensible, open-sourced version of the Entity Framework Data Access Technology built for .NET Core Applications. It is essentially a way to read and write data in a flexible and easier way. EFCore is an ORM ( Object Relational Mapper) built over ADO.NET that enables developers to access & store data much more efficiently without compromising on the performance (Unless you write real poor code!). With this technology, you no longer will interact directly with the database, like you used to do with traditional SQL queries and SPs.

What can I do with Entity Framework Core?

These are a few of the features of Entity Framework Core

  • Manage database connection
  • Configure models
  • Querying data
  • Saving data
  • Configure change tracking

Supported Database Providers

EFCore is intended for flexibility and rapid development. With that being said, EF supports a good like of database providers like SQL Server, MySQL, SQLite, In-memory, and PostgreSQL. For each of these providers, Microsoft has an extension to be installed from the NuGet package manager. The real flexibility this wide range of support provides is that you will not have to depend on the Database Provider ever again.

One fine day, your client wants to migrate to MySQL from SQL Server ( I don’t know why in the world anyone will do that, but taking as an example), It will be as easy to replace the connection string, installing the required package, and committing the migrations. You would NOT have to change your code even a bit, as EFCore takes care of data access. This is how you build decoupled applications the right way.

Various Development Approaches

There are 2 approaches while developing with Entity Framework Core in ASP.NET Core application namely. Code-First Approach and the Database-First Approach. It is quite obvious from the names.

With Code First Approach, you have the possibility to generate Database based on the Model classes and Rules applied while applying the migrations. In simple words, you could like a Student.cs class with the required properties, hook it up with a context class, and run some commands on your console BOOM! you have your database ready, based on Student.cs

As the name suggests, DB First approach is used when you already have a defined database with existing data. What EF Core does in this scenario is quite interesting. In the previous approach, we generated Tables from Model Classes, while using the DB First Approach we can generate Model classes from our existing Database Schema. Pretty cool, yeah?

In this episode, we will go through Code First Approach.


When Should I use Entity Framework Core?

You can go ahead with Entity Framework Core

  • if your application consists mostly of CRUD Operations only ( Create, Read, Write). Trust me, this is the case 9 out of 10 times.
  • if rapid development is necessary. With complex requirements, EFCore may have slower performance. But it is totally optimizable as well.
  • if you need a cleaner and well maintainable data access code.

When to NOT use Entity Framework Core?

Entity Framework Core may not be a good option if

  • if your application has to perform bulk operation on the database with Millions of records. Raw SQL Approach / Stored Procedure is recommended for such requirements.
  • if your business logic is quite complicated to achieve with EF.

That being said, DO NOT THINK that you can use only one way to access data in an application. Practical systems often use both RAW SQL and Entity Framework Core within the application. This ensures that you have the best of both worlds. EFCore to query the data and perform quick operations, while Stored Procedures to perform complex, Bulk Updates.

The DB Context Class

DbContext class is the backbone of this entire concept. Treat DbContext class as a session with the database. An instance of this class allows us to do the data operations on the specified models. Here is how the DbContext Implementation would look like,

public class ApplicationContext : DbContext, IApplicationContext
public ApplicationContext(DbContextOptions<ApplicationContext> options)
: base(options)
public DbSet<Product> Products { get; set; }

Here, we can see that our DbContext Class has a Products entity defined as a property. This means that by using an instance of this DbContext class, we will be able to perform operations over the Product Entity.

Implementing Entity Framework Core in ASP.NET Core 3.1 WebApi - Code-First Approach

Let’s see how to implement the Code-First Approach of Entity Framework Core in ASP.NET Core 3.1. We will create a new ASP.NET Core 3.1 Project with API Template using Visual Studio 2019 Community. Like always, I will be leaving the GitHub Repository link of the finished source code at the end of this post,

Installing the Required EFCore Packages

Firstly, after creating the API Project, let’s installed the required packages for this tutorial. Run the following commands on your package manager console.

Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.Tools
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Swashbuckle.AspNetCore
Install-Package Swashbuckle.AspNetCore.Swagger
Install-Package Microsoft.VisualStudio.Web.CodeGeneration.Design

For this demonstration, we will be using SQLServer as our database provider. That is why I am installing the SQLServer extension of EntityFrameworkCore.

What good is an API without Swagger? Swagger is the first thing that I install on any APIs that I work on. It makes documentation and testing so easy.

Creating a Model

Create a new Class and Name it Entity.cs

public class Entity
public int Id { get; set; }

Why this Class? We will use this class as the base class for our future entities. Here we can define the common and secured properties like Id, CreatedDate, etc.

I will create a Student Model in the Models folder, and add a bunch of properties to it.

PRO TIP - Sometimes, writing lines of properties and adding the get and sets can be quite frustrating from a developer’s point of view. We like everything automated right? Here is a tip to auto-generate properties. Just type in prop and hit Tab twice. All you have to enter is the data type and the name of the property.

These are called Code-Snippets. I will write about this in another article. Efficient Coding!


public class Student : Entity
public int Age { get; set; }
public int Roll { get; set; }
public string Name { get; set; }
public int Class { get; set; }
public string Section { get; set; }

Adding the DataContext Class and Interface

Let’s name our implementation of the DbContext Class as ApplicationDbContext.cs and IApplicationDbContext.cs respectively.

public class ApplicationDbContext : DbContext
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
public DbSet<Student> Students { get; set; }
public async Task<int> SaveChanges()
return await base.SaveChangesAsync();

In this class, we have defined Student class as one of the entities that we intend to work with. Now, let’s extract an interface for this class. Here is yet another PRO-TIP.


By definition, we now have the means to interact with Student Entity. But we haven’t generated the database yet, have we.

Adding the Connection String.

Let’s add the connection string pointing to the database we need to connect to. It can either be an existing database or a completely new one. I am going to use a fresh database. Open up appsettings.json and add this piece of line to the top.

"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=developmentDb;Trusted\_Connection=True;MultipleActiveResultSets=true"

I am trying to connect to a localDb instance of the SQL Server. You can connect to a SQL Server Instance as well, by modifying the connection strings. You can refer here for connection string variants of SQL Server.

Configuring the Services

Now that we have finished setting up the bare minimum, let’s configure our ASP.NET Core Application to support Entity Framework Core and set up Swagger as well. Go to your Startup class and modify the ConfigureServices method as below.

public void ConfigureServices(IServiceCollection services)
services.AddDbContext<ApplicationDbContext>(options =>
b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());
#region Swagger
services.AddSwaggerGen(c =>
c.IncludeXmlComments(string.Format(@"{0}\\EFCore.CodeFirst.WebApi.xml", System.AppDomain.CurrentDomain.BaseDirectory));
c.SwaggerDoc("v1", new OpenApiInfo
Version = "v1",
Title = "EFCore.CodeFirst.WebApi",

Line #3 defined the name of the context class to be added. In our cases it is ApplicationDbContext.
Line #4 states that we are using SQL Server as our Database Provider.
Line #5 mentions the Connection string name that we have already defined in appsettings.json.
Line #6 Binds the Concrete Class and the Interface into our Application Container.

Now add the below code to the Configure method. This is to let the application know that we intent to use Swagger.

#region Swagger
// Enable middleware to serve generated Swagger as a JSON endpoint.
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
c.SwaggerEndpoint("/swagger/v1/swagger.json", "EFCore.CodeFirst.WebApi");

The 2 Most Important Commands



Remember these 2 commands always. This is what you will need every single time to make changes to your database schema.Open your package manager console and type in the following.

add-migration "added student entity"

Line #1 will add a new Migrations folder to your Project. This contains the schema data of your models. EFCore uses this data to generate the Tables. The Comment inside quotes is essentially the description you would give for this particular migration. In our case, we have added the student entity and hence this description.

Line #2 , as the command says, updates / creates the database.

You will receive a done message, indicating that the database has been generated properly. Let’s check it out. Go to View -> SQL Server Object Explorer. Here you can see various database and server available.


We have successfully created the Student Database using the Code First Approach of Entity Framework Core in ASP.NET Core! Now let’s move to perform CRUD Operations for the Student Entity. CRUD - Create, Read, Update and Delete.

For this, I will create a new Empty API Controller under the Controllers folder. I will call it Student Controller. On this controller, we will implement CRUD Operations

CRUD Operations

Below is the code for the Student Controller. I will explain it in a while.

namespace EFCore.CodeFirst.WebApi.Controllers
public class StudentController : ControllerBase
private IApplicationDbContext _context;
public StudentController(IApplicationDbContext context)
_context = context;
public async Task<IActionResult> Create(Student student)
await _context.SaveChanges();
return Ok(student.Id);
public async Task<IActionResult> GetAll()
var students = await _context.Students.ToListAsync();
if (students == null) return NotFound();
return Ok(students);
public async Task<IActionResult> GetById(int id)
var student = await _context.Students.Where(a => a.Id == id).FirstOrDefaultAsync();
if (student == null) return NotFound();
return Ok(student);
public async Task<IActionResult> Delete(int id)
var student = await _context.Students.Where(a => a.Id == id).FirstOrDefaultAsync();
if (student == null) return NotFound();
await _context.SaveChanges();
return Ok(student.Id);
public async Task<IActionResult> Update(int id, Student studentUpdate)
var student = _context.Students.Where(a => a.Id == id).FirstOrDefault();
if (student == null) return NotFound();
student.Age = studentUpdate.Age;
student.Name = studentUpdate.Name;
await _context.SaveChanges();
return Ok(student.Id);

Line #6 and #7 are for injecting our Instance of ApplicationDbContext to the Constructor of the Student Controller so that we have access to the instance readily.

The different CRUD Action Methods.

GetAll - Here we use the context instance to access the dataset of Student Entity to retrieve the list of all students.
GetById - Using LINQ, we access the Student Dataset and retrieve the record with respective Id. If the record does not exist, the API throws a NotFound Exception.
Create - Saves the passes record to the database and returns the Id.
Delete - Deletes the record with specific Id. Return a NotFound Exception if invalid
Update - Updates the database with the record by Id. For keeping it simple, we are only allowing the Age and Name Property to be updated.

Testing with Swagger

Let’s open Swagger and do some testing. (navigate to localhost:{portnumber}/swagger). This will open up Swagger UI.


Open the First Get Link where it says /api/Student and click on execute.


Here you can see that the repsonse body is empty. This is because we have not added any data to our Student Table. So, let’s add a new record. For this, go to POST Option, and click on Try it out.


Now you can see a success message with Id 1. It means that we have successfully added a new student record with id 1. Let’s query it. Again, go to the Get Option on Swagger and execute.


You can see that we are able to query the data we just entered. Let’s also check the Get by Id Option . Enter id 1 and execute, you will see the similar result. Quite simple, yeah?

Let’s try to update the record, and change the student’s Age and Name. Click on the Put Option and add the modification. Here we can change the age and Name.


Click on Execute. You will see the Id of currently updated record. I will leave it to you to check if the record has been updated properly. You can also try to delete the record.Feel free to modify the source code available on GitHub. Link posted below.


In this episode we covered the basics of Entity Framework Core in ASP.NET Core 3.1 Applications and also implemented the same. We will go through further topics like Database First Approach, Change Tracking, Model Building, Setting SQL Column Properties and much more in the next episode. If you have any queries or suggestions, please leave them in the comments section below. Thanks!

Frequently Asked Questions

Is Entity Framework Core Slow?

Performance is feature in Entity Framework Core. The Performance depends on how well you can write LINQ effeciently without overheads. Entity Framework can show lag when used for scenarios with Bulk operations on Millions of records.

Can you use Entity Framework with .NET Core?

Yes, Microsoft has release Entity Framework Core, which is flexible variant of Entity Framework build for .NET Core based Applications.

What does Entity Framework Core do?

Entity Framework Core is an ORM Framework for the .NET World. It allows developers to work with databases without even touching them. It makes DB related operations quite simple and effecient.

Support ❤️
If you have enjoyed my content and code, do support me by buying a couple of coffees. This will enable me to dedicate more time to research and create new content. Cheers!
Share this Article
Share this article with your network to help others!
What's your Feedback?
Do let me know your thoughts around this article.

Mukesh's .NET Newsletter 🚀

Join 5,000+ Engineers to Boost your .NET Skills. I have started a .NET Zero to Hero Series that covers everything from the basics to advanced topics to help you with your .NET Journey! You will receive 1 Awesome Email every week.