Skip to content

Aspnet Ef Core

DodaTech 4 min read

title: ASP.NET Core Entity Framework Core — Complete Guide to EF Core description: 'Learn Entity Framework Core in ASP.NET: DbContext, entities, LINQ queries, relationships, eager loading, migrations, performance optimization, and best practices.' date: 2026-06-28 lastmod: 2026-06-28 weight: 22 tags: [backend, aspnet]


Entity Framework Core is a lightweight, cross-platform ORM for .NET that maps C# objects to database tables, supporting LINQ queries, change tracking, and migrations.

## What You'll Learn

By the end of this tutorial, you'll configure DbContext, define entities with relationships, write LINQ queries, manage migrations, optimize performance, and handle concurrency.

## Real-World Use

An ASP.NET Core e-commerce app uses EF Core to map Categories, Products, and Orders. LINQ queries fetch data with eager loading. Migrations evolve the schema with zero data loss.

## EF Core Learning Path

```mermaid
flowchart LR
  A[Config] --> B[EF Core]
  B --> C[Migrations]
  C --> D[Auth]
  D --> E[JWT]
  B --> F{You Are Here}
  style F fill:#f90,color:#fff

DbContext Setup

using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
    public DbSet<Product> Products => Set<Product>();
    public DbSet<Category> Categories => Set<Category>();
    public DbSet<Order> Orders => Set<Order>();
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>(entity =>
        {
            entity.Property(p => p.Price).HasPrecision(18, 2);
            entity.HasIndex(p => p.CategoryId);
        });
    }
}
// Program.cs
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

Entity Configuration

// Data Annotations
public class Product
{
    public int Id { get; set; }
    [Required, MaxLength(200)]
    public string Name { get; set; } = "";
    [Column(TypeName = "decimal(18,2)")]
    public decimal Price { get; set; }
    public int CategoryId { get; set; }
    [ForeignKey(nameof(CategoryId))]
    public Category Category { get; set; } = null!;
    public ICollection<OrderItem> OrderItems { get; set; } = new List<OrderItem>();
}

// Fluent API (in OnModelCreating)
modelBuilder.Entity<Product>(e =>
{
    e.Property(p => p.Name).IsRequired().HasMaxLength(200);
    e.Property(p => p.Price).HasColumnType("decimal(18,2)");
    e.HasOne(p => p.Category)
     .WithMany(c => c.Products)
     .HasForeignKey(p => p.CategoryId)
     .OnDelete(DeleteBehavior.Restrict);
});

LINQ Queries

public class ProductService
{
    private readonly AppDbContext _db;
    public ProductService(AppDbContext db) => _db = db;
    
    // Basic query
    public async Task<List<Product>> GetAllAsync()
    {
        return await _db.Products.ToListAsync();
    }
    
    // Filtering with eager loading
    public async Task<List<Product>> GetByCategoryAsync(int categoryId)
    {
        return await _db.Products
            .Include(p => p.Category)
            .Where(p => p.CategoryId == categoryId)
            .OrderByDescending(p => p.Price)
            .ToListAsync();
    }
    
    // Projection
    public async Task<List<ProductDto>> GetDtosAsync()
    {
        return await _db.Products
            .Select(p => new ProductDto(p.Id, p.Name, p.Price))
            .ToListAsync();
    }
    
    // Aggregation
    public async Task<decimal> GetAveragePriceAsync()
    {
        return await _db.Products.AverageAsync(p => p.Price);
    }
}

Relationships

// One-to-Many
public class Category
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public ICollection<Product> Products { get; set; } = new List<Product>();
}

// Many-to-Many (.NET 5+)
public class Student
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public ICollection<Course> Courses { get; set; } = new List<Course>();
}
public class Course
{
    public int Id { get; set; }
    public string Title { get; set; } = "";
    public ICollection<Student> Students { get; set; } = new List<Student>();
}
// EF Core 5+ creates the join table automatically

Common Mistakes

1. N+1 Queries

Without Include(), accessing navigation properties in a loop issues N separate queries. Always eager load.

2. Not Using Async

Blocking calls like ToList() instead of ToListAsync() waste threads. Use async methods for I/O.

3. Tracking Too Many Entities

By default, EF Core tracks changes. Use AsNoTracking() for read-only queries to reduce memory.

4. Loading All Data

Fetching thousands of rows without pagination. Use Skip() and Take() for pagination.

5. Ignoring Database Indexes

Queries without proper indexes scan entire tables. Add indexes with HasIndex() in OnModelCreating.

Practice Questions

1. What is EF Core?

An open-source ORM that maps C# objects to database tables with LINQ queries, change tracking, and migrations.

2. How do you eager load related data?

Use .Include(p => p.Category) and .ThenInclude(p => p.SubCategory) for nested relationships.

3. What is the difference between FirstOrDefault and SingleOrDefault?

FirstOrDefault returns first match (or null). SingleOrDefault expects exactly one (throws if multiple found).

4. How do you handle concurrency conflicts?

Add a [Timestamp] byte[] property. EF Core checks it on update and throws DbUpdateConcurrencyException on conflict.

5. Challenge: Create a complete query that returns products with their category names, ordered by price.

var products = await _db.Products
    .AsNoTracking()
    .Include(p => p.Category)
    .Where(p => p.Price > 10)
    .OrderByDescending(p => p.Price)
    .Select(p => new { p.Name, p.Price, Category = p.Category.Name })
    .ToListAsync();

FAQ

Is EF Core suitable for high-traffic apps?

Yes, with AsNoTracking(), compiled queries, and proper indexing. Stack Overflow uses EF Core.

Should I use Database First or Code First?

Code First gives you full control. Database First works for existing databases. Both are supported.

What is the difference between EF6 and EF Core?

EF Core is cross-platform, lighter, supports NoSQL, and has better performance. EF6 is Windows-only but more mature.

How do I log SQL queries from EF Core?

Enable sensitive data logging: options.EnableSensitiveDataLogging(). Use ToQueryString() for the generated SQL.

Can EF Core work with PostgreSQL or MySQL?

Yes. Use Npgsql for PostgreSQL, Pomelo for MySQL, or the official SQL Server provider.

Mini Project: Product-Category EF Core Setup

Configure EF Core for a product catalog with categories, including eager loading and queries.

builder.Services.AddDbContext<CatalogDb>(o => o.UseSqlServer(connStr));
public class CatalogDb : DbContext
{
    public DbSet<Product> Products => Set<Product>();
    public DbSet<Category> Categories => Set<Category>();
}
var products = await db.Products.Include(p => p.Category)
    .Where(p => p.Category.Name == "Electronics")
    .OrderBy(p => p.Price)
    .Select(p => new { p.Name, p.Price })
    .ToListAsync();

What's Next

ASP.NET Core Migrations ASP.NET Core Authentication

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro