In today’s development environment, most applications interact with databases to save data. There are multiple ways to interact with databases, but the most common industry standard is using an ORM. ORM stands for object-relational mapping and is used to interact with databases using object-oriented programming.
ORM allows us to access and manage databases using object-oriented concepts instead of writing raw SQL queries. This helps in improving developer productivity and code maintainability. Multiple ORMs are available in the market, such as Dapper and Entity Framework Core; however, in this blog, we’ll focus on Entity Framework Core and develop a console-based application that covers the basic database CRUD (Create, Read, Update, and Delete) operations using EF Core and C#.
Entity Framework Core is an object-relational mapper for .NET that enables developers to access databases using .NET objects without writing raw SQL queries. It is an open-source and lightweight ORM that works on many platforms, including Windows, macOS, and Linux. EF core works with different database providers such as SQL Server, SQLite, MySQL, PostgreSQL, Azure Cosmos DB, and others.
To work with EF Core, the most important concept is the model which consists of an entity class and a context object. An entity class represents a table, such as a Student
, and the context object represents a session with a database. There are multiple ways to create the model. In situations where a database already exists, we can create a model using the existing database. However, in cases where a database is not already present and we start the application development by creating the model first using hand code, we can use this newly created model to create the underlying database using EF Migrations and use these migrations to evolve the database as the model changes. For example, the following code represents a model that consists of a Student
entity class and a StudentContext
context class to interact with the database.
public class Student{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }}
public class StudentContext : DbContext{public DbSet<Student> Students { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){optionsBuilder.UseSqlServer("Connection string");}}
In the above code, the Student
class represents a student object with Id
, Name
, and Age
properties, and the StudentContext
class contains the property Students
of type DbSet
that represents the student table and a method OnConfiguring
to mention the connection string of the underlying database. We’ll go through the complete details of the above classes later in the getting started section of this blog. Let’s dive into the features and benefits of using EF Core.
EF Core provides many features and benefits for developers to help them write a cleaner, more efficient, and more organized code base. Some of the most important features are listed below.
Cross-platform: Entity Framework Core is designed to be a cross-platform ORM and can run on Windows, Linux, and macOS. This means developers can deploy applications across various platforms without worrying about platform dependency.
Database providers: EF Core supports multiple database providers, including SQL Server, SQLite, Azure SQL Database, Azure Cosmos DB, MySQL, PostgreSQL, and more. This allows developers to switch the underlying database easily without changing the application code significantly.
Code-first and database-first approach: Entity Framework Core allows developers to work either with code-first or database-first approaches. In the code-first approach, the developer defines the model first, and EF generates a database using this model. In the database-first approach, the model is generated using an existing database.
Migrations: EF Core tracks and maintains the changes made to the database structure through migrations that are code-based files. This simplifies the process of evolving the database schema and provides the versioned history of schema changes.
LINQ support: EF core support LINQ queries. This means the developers can use C# code to write expressive and type-safe queries to access the database. EF Core automatically converts these LINQ queries into SQL queries to be executed on the underlying database.
Lazy loading: EF Core provides a feature of lazy loading that allows related data to be loaded from the database only when explicitly requested. This helps improve the application’s performance by fetching only the required data at a given moment.
Change tracking: EF Core tracks the changes to loaded entities through the change tracking feature. This is a crucial and important feature of EF Core through which it keeps a record of entity state (Added
, Unchanged
, Modified
, Deleted
) and the developer does not need to worry about keeping track of entity changes.
Performance: EF Core improves performance through features like query optimization, batched statement execution, compiled queries, and connection pooling. It also offers options for eager loading, explicit loading, and executing raw SQL queries, allowing developers to optimize database interaction based on specific needs.
This set of rich features makes Entity Framework Core a perfect choice for .NET developers who want to integrate ORM in their applications to access and manage the database using object-oriented concepts. In the next section, we will develop a console application using EF Core.
This section discusses the steps involved in building a basic console-based application that uses EF Core as an ORM. We will use the code-first approach in this example. Moreover, we will demonstrate how to perform CRUD operations, install EF Core, define the model, run migration commands, and execute the application. For this blog, we will use C# as our implementation language. However, EF Core can also be used with F# and Visual Basic. So let’s get started.
The first step is to create an application in which we require EF Core for database interaction. It can be of any type, e.g., console desktop, web, or cloud-based. To simplify things, we will create a console-based application using the following CLI command.
dotnet new console -o MyFirstEFApplication
The above command creates a default console-based application.
The next step is to install the Entity Framework Core-related packages. The first package to be installed is related to the database provider. To use EF Core in an application, we need to install the package for the database provider we want. For example, if we want to use an SQL Server database, we will install the EF Core for SQL Server and if we want to use an in-memory database, we will install the EF Core for an in-memory database.
EF Core is shipped as a NuGet package and requires the most recent version of the .NET SDK installed on the system. We can install the EF Core SQL Server provider NuGet package using the following .NET Core CLI command from the operating system’s command line.
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
In this blog, we will use the in-memory database to remove the dependency of any database vendor. Using an in-memory database eliminates the need for any physical database server, making the setup and execution of the blog faster and more suitable for testing scenarios. Please note that the in-memory database is transient and won’t retain data beyond the lifetime of the application.
Go to the directory where we created the console application and execute the following command.
dotnet add package Microsoft.EntityFrameworkCore.InMemory
Once the EF Core in-memory provider is installed using the above command, we’ll install the EF Core tools used to create and apply database migrations. We can install these tools using the following command.
dotnet tool install --global dotnet-ef
The commands included in this set of tools begin with dotnet ef
as we’ll see shortly. Next, install the following package that is required for the EF Core tools to work.
dotnet add package Microsoft.EntityFrameworkCore.Design
In this step, we’ll create a model consisting of an entity and context classes, as discussed previously. Let’s assume that we are making an e-commerce application where we need to show or save the products, so the basic entity in our case is a product. We’ll make a Product
class to represent this entity as shown below.
public class Product{public int Id { get; set; }public string? Name { get; set; }public decimal Price { get; set; }}
We can use any code editor to make this class; however, in this blog, we have used the Visual Studio code editor to create a new file named Product.cs
and pasted the above code in this file. EF Core will automatically create a table to save the product information by using this entity after executing the migration commands we will see in the later step.
Once we create the entity class, the next step is creating a context class representing the session with the database. In our case, we’ll create a ProductDbContext
class as shown below.
using Microsoft.EntityFrameworkCore;public class ProductDbContext : DbContext{public DbSet<Product> Products { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){// Use the in-memory database provideroptionsBuilder.UseInMemoryDatabase("InMemoryDb");//optionsBuilder.UseSqlServer("your_connection_string_here");}}
In the above class, please note that we inherit this class with the DbContext
class provided by EF Core and create a property Products
of type DbSet
to represent the table of products. Moreover, if we have more entity classes in our codebase, we need to define the DbSet
property for each such entity class in this context class to create database tables against these classes.
In the OnConfiguring
method, you must replace the “your_connection_string_here”
with the actual connection string according to your development environment if you’re using the SQL Server. However, as we are using an in-memory database for this blog, we do not need to perform this step of replacing the connection string.
Once we have set up the model, the next step is to create a database using this model. As we are demonstrating a code-first approach in which a database is generated using the model, we’ll use the commands that are installed by EF Core tools and start with dotnet ef
Use the following commands to perform migrations:
dotnet ef migrations add InitialDBdotnet ef database update
These commands create a migration based on your model and apply it to the database, which results in creating a new database. Please note that this step is only needed for physical database providers such as SQL Server. In the case of an in-memory database, we do not perform this step.
In this step, we’ll guide you through implementing CRUD operations for the Product
class that we have created in the previous step. The first operation that we’ll implement is the Create operation in which a new product object will be created using EF Core. The following code demonstrates the creation of a new product object.
using (var context = new ProductDbContext()){// Createvar newProduct = new Product { Name = "Sample Product", Price = 29.99M };context.Products.Add(newProduct);context.SaveChanges();}
We’ll write this code in the program.cs
file that you can find in the console application directory we created in the first step. The above code creates a new product and saves it into the underlying database using the context class. Note that we do not need raw SQL statements to insert a product into the database. We use object-oriented concepts to create a product object and then use methods to perform the Create operation. We’ll demonstrate the Read operation using the following code in the next step.
var context = new ProductDbContext();var products = context.Products.ToList();foreach (var product in products){Console.WriteLine($"Product: {product.Name}, Price: {product.Price}");}
In the code above, we have used the context class and ToList()
method to get all the products from the database. As we discussed in the feature section, we can also use LINQ queries here to retrieve the products based on conditions. That would be equivalent to using the where
clause in SQL. In the next operation, we will demonstrate how to Update a product using the following code.
var context = new ProductDbContext();var productToUpdate = context.Products.FirstOrDefault(p => p.Name == "Sample Product");if (productToUpdate != null){productToUpdate.Price = 39.99M;context.SaveChanges();}
To update a product, we first need to retrieve it using EF Core. As we can see in the above code, we are retrieving the first product based on the condition using the context
object. After that, if we find the product, we update its price and save it to the database using the SaveChanges
method. The last operation, Delete, is demonstrated using the following code.
var context = new ProductDbContext();var productToDelete = context.Products.FirstOrDefault(p => p.Name == "Sample Product");if (productToDelete != null){context.Products.Remove(productToDelete);context.SaveChanges();}
In the code above, we use the Remove
method along with SaveChanges
to remove the product from the database, This completes the implementation of CRUD operations.
We’ll use the following command to execute the application.
dotnet run
The above command will show the output on the console. The complete steps are also illustrated with the help of the following slides.
This completes the steps to perform the CRUD operations using EF Core. The blog also shows how we have used object-oriented concepts for database operations instead of writing raw SQL queries using EF Core ORM.
We hope this blog has helped you understand the basics of the Entity Framework Core. To learn more about this technology, please refer to the following courses:
This course introduces Entity Framework Core for data access and object-relational mapping. Entity Framework Core provides benefits such as the ability to work with databases using .NET objects without the concern for underlying database tables. This leads to less code for data access and improved performance. You’ll begin with the workflows of Entity Framework Core—reverse engineering and migrations. Next, you’ll learn model configuration and relationships. Then, you’ll cover various methods for querying and saving data. You’ll also learn about change tracking and its relationship with queries. Finally, you’ll learn about logging and testing. Entity Framework Core simplifies app development. By the end of this course, you’ll be able to improve code maintainability and concentrate on business logic by generating SQL, materializing results, and performing other tasks. You’ll have a good understanding of Entity Framework Core, which will improve your productivity and efficiency on your development journey.
.NET is Microsoft’s free and open source framework for developing native software applications on Linux, macOS, and Windows. The power of cross-platform development allows developers to design, code, and run programs on a wide array of platforms. This course is an introduction to developing .NET applications using C#. You’ll start start with a comprehensive review of C# and computer programming fundamentals: data types, conditionals, loops, methods, and more. You’ll then review the basics of object-oriented programming before diving into methods, exception handling, delegation, and events. With this foundation, you’ll continue building interfaces, collections, database operations, and multithreading. You’ll wrap up with process improvements using dynamic binding, garbage collection, and unmanaged resources. By the end of this course, you’ll have hands-on experience with C# and .NET, and be ready to build applications using object-oriented programming principles on almost any platform.
Free Resources