Table of Contents
- Prerequisites
- What is Entity Framework Core?
- Setting Up EF Core
- Creating a Data Model
- The DbContext: Your Gateway to the Database
- Connecting to a Database
- CRUD Operations with EF Core
- Managing Database Schema with Migrations
- Conclusion
- References
Prerequisites
Before we start, ensure you have the following:
- .NET SDK: Install the latest .NET SDK (v6.0 or later recommended).
- Code Editor: Use Visual Studio (Community Edition is free) or VS Code with the C# extension.
- Basic C# Knowledge: Familiarity with classes, objects, and LINQ (Language Integrated Query) will help.
What is Entity Framework Core?
Entity Framework Core is an ORM— a tool that bridges the gap between object-oriented programming (OOP) and relational databases. It allows you to:
- Map C# classes (entities) to database tables.
- Query data using LINQ instead of SQL.
- Insert, update, and delete records using C# objects.
- Automatically generate database schemas from your C# models.
In short, EF Core acts as a middleman, translating your C# code into SQL and vice versa.
Setting Up EF Core
Step 1: Install .NET SDK
If you haven’t already, install the .NET SDK. Verify the installation by running this command in your terminal:
dotnet --version
You should see a version number (e.g., 7.0.100).
Step 2: Create a New Project
Let’s build a simple console app to demonstrate EF Core. Open your terminal and run:
dotnet new console -n EFCoreDemo
cd EFCoreDemo
This creates a new console project named EFCoreDemo and navigates into its folder.
Step 3: Install EF Core NuGet Packages
EF Core requires two main packages:
- EF Core Runtime: The core library (
Microsoft.EntityFrameworkCore). - Database Provider: A package specific to your database (e.g., SQL Server, SQLite, PostgreSQL).
For this guide, we’ll use SQLite (a lightweight, file-based database) because it requires no separate server setup. Install the required packages via the terminal:
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
If you prefer SQL Server, use Microsoft.EntityFrameworkCore.SqlServer instead.
Creating a Data Model
A model in EF Core is a C# class that represents a database table. Each property in the class maps to a column in the table. Let’s create a simple model for a Book entity.
Entity Classes
Add a new folder named Models in your project, then create a Book.cs file with the following code:
// Models/Book.cs
namespace EFCoreDemo.Models;
public class Book
{
public int Id { get; set; } // Primary Key
public string Title { get; set; } // Book title
public string Author { get; set; } // Author name
public int Pages { get; set; } // Number of pages
public decimal Price { get; set; } // Price
}
Here, Book is our entity. By convention:
Idis the primary key (EF Core automatically recognizesIdorBookIdas the primary key).- Other properties (e.g.,
Title,Author) map to columns in theBookstable (EF Core pluralizes class names for table names by default).
Data Annotations for Model Configuration
Sometimes, you need to customize how entities map to the database (e.g., set a column name, mark a field as required). Use data annotations to configure your model:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EFCoreDemo.Models;
public class Book
{
[Key] // Explicitly mark as primary key (optional, but clear)
public int BookId { get; set; } // Custom primary key name
[Required] // Ensures the column is NOT NULL
[MaxLength(200)] // Limits title length to 200 characters
public string Title { get; set; }
[Column("Writer")] // Maps to a database column named "Writer" instead of "Author"
public string Author { get; set; }
[Range(1, 2000)] // Ensures Pages is between 1 and 2000
public int Pages { get; set; }
[Column(TypeName = "decimal(18,2)")] // Sets SQL data type (e.g., for currency)
public decimal Price { get; set; }
}
The DbContext: Your Gateway to the Database
What is DbContext?
The DbContext class is the heart of EF Core. It:
- Manages database connections.
- Tracks changes to entities (e.g., when you add or update an object).
- Provides access to database tables via
DbSet<T>properties.
Think of DbContext as a “session” with the database.
Configuring DbContext
Create a Data folder in your project, then add a AppDbContext.cs file:
using Microsoft.EntityFrameworkCore;
using EFCoreDemo.Models;
namespace EFCoreDemo.Data;
public class AppDbContext : DbContext
{
// DbSet<T> represents a table in the database.
public DbSet<Book> Books { get; set; }
// Configure the database connection
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// Use SQLite and specify the database file path
optionsBuilder.UseSqlite("Data Source=EFCoreDemo.db");
}
}
DbSet<Book> Books: Represents theBookstable in the database. You’ll use this to query, add, update, or deleteBookentities.OnConfiguring: Configures the database provider (SQLite in this case) and connection string.
Connecting to a Database
Choosing a Database Provider
EF Core supports multiple databases (SQL Server, PostgreSQL, MySQL, SQLite, etc.). Each requires a specific NuGet package:
| Database | NuGet Package Name |
|---|---|
| SQL Server | Microsoft.EntityFrameworkCore.SqlServer |
| SQLite | Microsoft.EntityFrameworkCore.Sqlite |
| PostgreSQL | Npgsql.EntityFrameworkCore.PostgreSQL |
| MySQL | Pomelo.EntityFrameworkCore.MySql |
We’re using SQLite, so we already installed Microsoft.EntityFrameworkCore.Sqlite.
Setting Up a Connection String
A connection string tells EF Core how to connect to your database. For SQLite, it’s a file path (the database will be created automatically if it doesn’t exist).
In the OnConfiguring method above, we hardcoded the connection string:
optionsBuilder.UseSqlite("Data Source=EFCoreDemo.db");
For production apps, never hardcode connection strings! Instead, store them in appsettings.json and use dependency injection. For simplicity, we’ll use the hardcoded approach here, but we’ll mention the better practice later.
CRUD Operations with EF Core
Now that we have a model and DbContext, let’s perform the four core database operations: Create, Read, Update, Delete.
Create: Adding Entities
To add a new Book to the database:
- Create a
Bookobject. - Add it to the
DbSet<Book>(viaAppDbContext). - Call
SaveChanges()to persist the change to the database.
Update Program.cs (the entry point of your console app) with this code:
using EFCoreDemo.Data;
using EFCoreDemo.Models;
// Create a new Book object
var newBook = new Book
{
Title = "The Great Gatsby",
Author = "F. Scott Fitzgerald",
Pages = 180,
Price = 12.99m
};
// Create a DbContext instance
using (var context = new AppDbContext())
{
// Add the book to the Books table
context.Books.Add(newBook);
// Save changes to the database
context.SaveChanges();
Console.WriteLine($"Added book with ID: {newBook.BookId}");
}
Run the app with:
dotnet run
EF Core will create the EFCoreDemo.db file in your project folder and insert the new book.
Read: Querying Entities
To retrieve data, use LINQ queries on the DbSet<Book>. Here are common examples:
Get All Books
using (var context = new AppDbContext())
{
var allBooks = context.Books.ToList();
Console.WriteLine("All Books:");
foreach (var book in allBooks)
{
Console.WriteLine($"- {book.Title} by {book.Author} (${book.Price})");
}
}
Get a Single Book by ID
using (var context = new AppDbContext())
{
int bookId = 1; // Replace with the ID of the book you added
var book = context.Books.FirstOrDefault(b => b.BookId == bookId);
if (book != null)
{
Console.WriteLine($"Found: {book.Title}");
}
else
{
Console.WriteLine("Book not found.");
}
}
Filter Books with LINQ
Use Where to filter results (e.g., find all books by “J.K. Rowling”):
var rowlingBooks = context.Books
.Where(b => b.Author == "J.K. Rowling")
.OrderBy(b => b.Title)
.ToList();
Update: Modifying Entities
To update an existing book:
- Retrieve the book from the database.
- Modify its properties.
- Call
SaveChanges()to apply the update.
using (var context = new AppDbContext())
{
int bookId = 1;
var bookToUpdate = context.Books.FirstOrDefault(b => b.BookId == bookId);
if (bookToUpdate != null)
{
bookToUpdate.Price = 14.99m; // Increase price
context.SaveChanges();
Console.WriteLine($"Updated price of {bookToUpdate.Title} to ${bookToUpdate.Price}");
}
}
Delete: Removing Entities
To delete a book:
- Retrieve the book.
- Remove it from the
DbSet. - Call
SaveChanges().
using (var context = new AppDbContext())
{
int bookId = 1;
var bookToDelete = context.Books.FirstOrDefault(b => b.BookId == bookId);
if (bookToDelete != null)
{
context.Books.Remove(bookToDelete);
context.SaveChanges();
Console.WriteLine($"Deleted book: {bookToDelete.Title}");
}
}
Managing Database Schema with Migrations
So far, we’ve let EF Core create the database schema automatically. But what if you modify your model later (e.g., add a PublicationYear property to Book)? You could delete the database and let EF Core recreate it, but that would lose data.
Migrations solve this problem. Migrations are a set of files that track changes to your model and let you apply those changes to the database schema incrementally.
What Are Migrations?
Migrations:
- Generate SQL scripts to update the database schema.
- Preserve existing data (when possible).
- Let you roll back changes if needed.
Creating and Applying Migrations
Step 1: Install the EF Core Tools
First, install the EF Core CLI tools (required to work with migrations):
dotnet tool install --global dotnet-ef
Step 2: Create Your First Migration
Let’s modify the Book model to add a PublicationYear property:
public class Book
{
// ... existing properties ...
public int PublicationYear { get; set; } // New property
}
Now, create a migration to reflect this change:
dotnet ef migrations add AddPublicationYearToBook
add: The command to create a migration.AddPublicationYearToBook: A descriptive name for the migration.
EF Core will generate a new folder Migrations with files like 20240101000000_AddPublicationYearToBook.cs (the timestamp ensures order).
Step 3: Apply the Migration
Run the migration to update the database schema:
dotnet ef database update
EF Core will execute the SQL in the migration file, adding the PublicationYear column to the Books table.
Step 4: Verify the Change
Check the database to confirm the column was added. You can use tools like DB Browser for SQLite to open EFCoreDemo.db and inspect the Books table.
Conclusion
Congratulations! You’ve learned the basics of Entity Framework Core:
- Setting up EF Core and connecting to a database.
- Creating models and
DbContext. - Performing CRUD operations with LINQ.
- Managing schema changes with migrations.
EF Core is a vast library, and there’s much more to explore (e.g., relationships between entities, advanced querying, dependency injection). But with this foundation, you can start building data-driven C# apps with confidence.
References
Happy coding! 🚀