Getting Started with EF Core: Part 1

Table of Contents

  1. Introduction
  2. Overview of EF Core
    • Key Features
  3. Getting Started with EF Core
    • Step 1: Install EF Core Packages
    • Step 2: Define a Database Context
    • Step 3: Configure Dependency Injection
  4. Defining Relationships in EF Core
    • One-to-One Relationship
    • One-to-Many Relationship
    • Many-to-Many Relationship
  5. EF Core vs Dapper
    • Architectural Perspective
  6. Conclusion

Introduction

Entity Framework Core (EF Core) is a modern, lightweight, open-source object-relational mapper (ORM) for .NET applications. It provides developers with an efficient way to interact with databases using .NET objects, eliminating the need for most raw SQL code. In this first part of our EF Core series, we will cover an overview of EF Core and discuss some fundamental features, including adding a database context, dependency injection, and defining relationships such as one-to-one, one-to-many, and many-to-many.

Overview of EF Core

EF Core is a cross-platform ORM that enables developers to work with relational databases such as SQL Server, PostgreSQL, MySQL, and SQLite using .NET objects. It supports LINQ queries, change tracking, migrations, and schema generation based on your .NET models.

Key Features

  • Cross-Platform Support: Runs on Windows, macOS, and Linux.
  • LINQ Support: Allows developers to write strongly typed queries using LINQ.
  • Migration Management: Provides tools to manage database schema changes.
  • Change Tracking: Tracks changes in your .NET objects and automatically translates them into database commands.
  • Asynchronous Queries: Fully supports async programming, enabling better scalability.
  • Rich Relationship Management: Simplifies handling relationships between tables with minimal configuration.
  • Automatic Schema Creation: Generates database schema directly from your .NET models.

From an architectural perspective, EF Core is ideal for applications where maintainability, abstraction, and developer productivity are priorities. Its rich feature set simplifies complex operations, making it a suitable choice for large-scale enterprise applications.

Getting Started with EF Core

To use EF Core, you need to install the required NuGet packages and configure them in your project.

Step 1. Install EF Core Packages.

# For SQL Server
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

# For Tools like Migrations
dotnet add package Microsoft.EntityFrameworkCore.Tools

Step 2. Define a Database Context.

The DbContext class is the backbone of EF Core. It manages the connection to the database and facilitates CRUD operations.

using Microsoft.EntityFrameworkCore;
 
public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) {}
 
    public DbSet<Product> Products { get; set; }
    public DbSet<Category> Categories { get; set; }
}

In this example, Products and Categories represent tables in the database.

Step 3. Configure Dependency Injection.

EF Core integrates seamlessly with ASP.NET Core’s dependency injection system. To configure the DbContext, you can add it to the service container in the Program.cs.

using Microsoft.EntityFrameworkCore;
 
var builder = WebApplication.CreateBuilder(args);
 
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
 
var app = builder.Build();
 
app.Run();

Defining Relationships in EF Core

EF Core supports various types of relationships between entities.

1. One-to-One Relationship

A one-to-one relationship occurs when one entity is related to exactly one other entity.

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public UserProfile Profile { get; set; }
}
 
public class UserProfile
{
    public int Id { get; set; }
    public string Bio { get; set; }
    public int UserId { get; set; }
    public User User { get; set; }
}
 
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasOne(u => u.Profile)
        .WithOne(p => p.User)
        .HasForeignKey<UserProfile>(p => p.UserId);
}

2. One-to-Many Relationship

A one-to-many relationship occurs when one entity is related to multiple other entities.

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Product> Products { get; set; }
}
 
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int CategoryId { get; set; }
    public Category Category { get; set; }
}
 
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Category>()
        .HasMany(c => c.Products)
        .WithOne(p => p.Category)
        .HasForeignKey(p => p.CategoryId);
}

3. Many-to-Many Relationship

A many-to-many relationship occurs when multiple entities are related to multiple other entities.

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Book> Books { get; set; }
}
 
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public ICollection<Author> Authors { get; set; }
}
 
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Author>()
        .HasMany(a => a.Books)
        .WithMany(b => b.Authors)
        .UsingEntity(j => j.ToTable("AuthorBooks"));
}

EF Core vs Dapper

EF Core and Dapper are two popular ways to interact with databases in .NET applications. Here is a comparison of their key differences.

Feature EF Core Dapper
Type Full-fledged ORM Micro-ORM
Querying LINQ and strongly-typed queries Raw SQL and dynamic queries
Ease of Use Easier to set up relationships Simpler for straightforward queries
Performance Slightly slower due to abstraction Faster for read-heavy applications
Features Change tracking, migrations, etc. Lightweight with fewer built-in tools
Learning Curve Moderate, especially for beginners Low, easier for developers familiar with SQL


Architectural Perspective

From an architect’s point of view, EF Core offers.

  • Higher abstraction: Simplifies database operations, reducing boilerplate code.
  • Maintainability: With migrations and schema management, it becomes easier to handle changes.
  • Standardization: Ensures consistency across the application through the use of LINQ and conventions.
  • Productivity Gains: Developers can focus more on business logic rather than database intricacies.

Dapper, on the other hand, is preferred when,

  • Performance is critical: For applications requiring extremely fast read operations.
  • Fine-grained control: When developers need precise SQL queries for complex operations.
  • Lightweight solutions: For small-scale applications or services with limited relational complexity.

When to Use EF Core?

  • Applications with complex relationships and frequent schema updates.
  • Scenarios where automatic change tracking and migrations are beneficial.

When to Use Dapper?

  • High-performance scenarios requiring raw SQL.
  • Applications with simpler database requirements and no need for ORM features.

Conclusion

In this first part of our EF Core series, we explored the basics of EF Core, including setting up a database context, integrating it with ASP.NET Core through dependency injection, and defining relationships between entities. From an architectural standpoint, EF Core provides abstraction, maintainability, and developer productivity, making it a strong choice for enterprise applications. We also compared EF Core with Dapper to understand their differences and use cases. In the next part, we will dive into advanced EF Core features such as querying, performance optimization, and migrations.

Up Next
    Ebook Download
    View all
    Learn
    View all