Install Entity Framework Core Beginner-Friendly Guide

Install EF Core Fast: Step-by-Step Beginner’s Guide

Install EF Core fast with this step‑by‑step guide: add packages, run migrations, and write your first query in .NET.

.NET Development Databases·By amarozka · October 12, 2025

Install EF Core Fast: Step-by-Step Beginner’s Guide

Want EF Core running in under 10 minutes without guesswork? Follow this path and you’ll have migrations created, a database on disk, and your first query printed to the console.

What you’ll build

We’ll set up a tiny data layer with SQLite (no server needed), create a migration, apply it, and run a query. You’ll also see quick switches for SQL Server and PostgreSQL.

Plan:

  1. Create a new .NET project.
  2. Add EF Core packages.
  3. Write a DbContext and a simple entity.
  4. Create and apply a migration.
  5. Insert sample data and run the first query.
  6. Switch providers (optional) and fix common errors.

I use this exact flow on fresh laptops during workshops. It’s fast, predictable, and easy to repeat.

Prerequisites

  • .NET SDK 8+ installed (dotnet --version should print a number).
  • A terminal (PowerShell, bash, or the VS Terminal).
  • Optional: Visual Studio or VS Code.

If you use Visual Studio’s Package Manager Console (PMC), I’ll show the matching commands too.

Step 1 – Create a clean project

You can use a console app or a minimal API. Let’s keep it simple with a console app:

mkdir EfCoreFastStart
cd EfCoreFastStart

dotnet new console -n EfCoreFastStart
cd EfCoreFastStart

The folder now contains Program.cs and a project file EfCoreFastStart.csproj.

Step 2 – Add EF Core packages

For SQLite (a single file database):

dotnet add package Microsoft.EntityFrameworkCore.Sqlite

For migrations support (required for CLI migrations):

dotnet add package Microsoft.EntityFrameworkCore.Design

Install the EF CLI tool once (global):

dotnet tool install --global dotnet-ef

Using Visual Studio instead? You can run the same operations from Package Manager Console: Add-Migration, Update-Database.

Other providers (optional now, details later):

  • SQL Server: dotnet add package Microsoft.EntityFrameworkCore.SqlServer
  • PostgreSQL: dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL

Step 3 – Create the model and context

We’ll track simple products. Create a new folder and two files.

mkdir Data

Data/Product.cs

namespace EfCoreFastStart.Data;

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public DateTime CreatedUtc { get; set; } = DateTime.UtcNow;
}

Data/ShopContext.cs

using Microsoft.EntityFrameworkCore;

namespace EfCoreFastStart.Data;

public class ShopContext : DbContext
{
    public DbSet<Product> Products => Set<Product>();

    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        // SQLite: database file will be created next to the EXE
        options.UseSqlite("Data Source=shop.db");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>()
            .Property(p => p.Name)
            .HasMaxLength(200);

        modelBuilder.Entity<Product>()
            .Property(p => p.Price)
            .HasPrecision(18, 2);
    }
}

Why this design?

  • OnConfiguring keeps the sample self‑contained (no DI needed for a console demo).
  • Precision on Price avoids awkward decimals.

Step 4 – Wire the app to apply migrations on startup

Open Program.cs and replace the contents with:

using EfCoreFastStart.Data;
using Microsoft.EntityFrameworkCore;

// Ensure database exists and is up to date
await using var db = new ShopContext();
await db.Database.MigrateAsync();

// Seed a few rows on first run
if (!await db.Products.AnyAsync())
{
    db.Products.AddRange(
        new Product { Name = "Coffee Beans", Price = 9.99m },
        new Product { Name = "Espresso Cup", Price = 4.50m },
        new Product { Name = "French Press", Price = 24.90m }
    );
    await db.SaveChangesAsync();
}

// First query
var cheap = await db.Products
    .Where(p => p.Price < 10)
    .OrderBy(p => p.Price)
    .ToListAsync();

foreach (var p in cheap)
{
    Console.WriteLine($"{p.Id}: {p.Name} - {p.Price:C}");
}

Note the line await db.Database.MigrateAsync();. This ensures your app applies pending migrations at runtime. During local development it saves time.

Step 5 – Create and apply the first migration

From the project folder (EfCoreFastStart/EfCoreFastStart):

dotnet ef migrations add InitialCreate

This generates a Migrations/ folder with migration files and a model snapshot.

Apply the migration (creates shop.db):

dotnet ef database update

Run the app:

dotnet run

Expected output (ids may differ):

1: Espresso Cup - $4.50
2: Coffee Beans - $9.99

If you see prices printed, congrats – EF Core is installed, the schema is created, and the first query worked.

Package Manager Console (Visual Studio) equivalents

Add-Migration InitialCreate
Update-Database

Step 6 – Change the model and create another migration (optional)

Let’s add a boolean flag and see the migration flow.

Edit Data/Product.cs:

public bool IsActive { get; set; } = true;

Create a migration and update the DB:

dotnet ef migrations add AddIsActiveToProduct

dotnet ef database update

That’s your basic change cycle.

Quick switches: SQL Server and PostgreSQL

SQLite is great for demos and tests. For a real app you may want SQL Server or PostgreSQL.

SQL Server

  1. Add provider:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
  1. Update context configuration (ShopContext.cs):
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
    options.UseSqlServer(
        "Server=localhost;Database=ShopDb;Trusted_Connection=True;TrustServerCertificate=True");
}
  1. New migration (if you changed provider on a clean repo you can delete old migrations first):
dotnet ef migrations add InitialCreateSqlServer

dotnet ef database update

PostgreSQL

  1. Add provider:
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
  1. Update context configuration:
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
    options.UseNpgsql("Host=localhost;Database=shopdb;Username=postgres;Password=postgres");
}
  1. Create and apply migrations as usual.

Tip: keep separate appsettings files per environment in real projects and move connection strings out of source code.

Minimal API sample (if you prefer an HTTP endpoint)

If you started with dotnet new web -n EfCoreFastStartApi, wire DI like this:

Program.cs

using EfCoreFastStart.Data;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<ShopContext>(opt =>
    opt.UseSqlite(builder.Configuration.GetConnectionString("Default") ?? "Data Source=shop.db"));

var app = builder.Build();

// Apply migrations automatically on startup (dev only)
using (var scope = app.Services.CreateScope())
{
    var db = scope.ServiceProvider.GetRequiredService<ShopContext>();
    db.Database.Migrate();
}

app.MapGet("/products/cheap", async (ShopContext db) =>
    await db.Products.Where(p => p.Price < 10).ToListAsync());

app.Run();

appsettings.json

{
  "ConnectionStrings": {
    "Default": "Data Source=shop.db"
  }
}

Run the app and call /products/cheap.

Troubleshooting (the part that saves hours)

“The term dotnet-ef is not recognized”

  • Install the tool: dotnet tool install --global dotnet-ef.
  • If already installed, ensure the global tools path is on your PATH. Restart the terminal after install.

“Unable to create a design-time DbContext”

  • EF CLI needs to create your context. With OnConfiguring, it should work.
  • If you moved to DI only, add a factory:
using EfCoreFastStart.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

public class ShopContextFactory : IDesignTimeDbContextFactory<ShopContext>
{
    public ShopContext CreateDbContext(string[] args)
    {
        var options = new DbContextOptionsBuilder<ShopContext>()
            .UseSqlite("Data Source=shop.db")
            .Options;
        return new ShopContext();
    }
}

(Or keep OnConfiguring in the context for demos.)

Build failed during migrations

  • Migrations run a build. Fix compile errors first.

“No provider configured”

  • Check you called UseSqlite, UseSqlServer, or UseNpgsql in configuration.

“Cannot open database” on SQL Server

  • Check instance name and trust settings. For local development, TrustServerCertificate=True often helps.

Migrations folder chaos

  • If you are still experimenting, you can delete the Migrations/ folder and the DB file, then start fresh: dotnet ef migrations add InitialCreatedotnet ef database update.

What did we just gain?

  • A repeatable EF Core setup you can drop into any small sample.
  • A working migration flow (add, update).
  • A sample query with async LINQ.
  • Clear switches for popular providers.

This is enough to start a real project without drowning in setup.

FAQ: quick answers for common questions

Do I need Microsoft.EntityFrameworkCore.Design?

Yes, for migrations created by the CLI. Without it, dotnet ef will complain.

Global tool vs local tool for dotnet-ef?

Global is fine for a single machine. In teams, consider a local tool manifest so everyone runs the same version:
dotnet new tool-manifest
dotnet tool install dotnet-ef

Then call: dotnet tool restoredotnet ef ....

Should I apply migrations at startup?

In dev, yes, it’s handy: Database.Migrate(). In prod, run migrations during deployment, not inside app startup.

Can I keep using SQLite in production?

It’s fine for small desktop tools and tests. For web apps or heavier data, use SQL Server, PostgreSQL, or another full server engine.

Where do I put connection strings?

appsettings.json or user secrets. Avoid hardcoding for anything beyond a demo.

What if I want separate read and write models?

That’s a bigger topic (CQRS). Start simple here; split later when you have a concrete need.

How do I seed data properly?

For demos, insert after Migrate(). For structured seeding, use modelBuilder.Entity<>().HasData(...) and add a migration.

Best way to map decimals?

Set precision in OnModelCreating (as shown). This avoids default mappings that may not match your needs.

Conclusion: you now have EF Core ready to work

You created a project, added packages, generated a migration, and ran a query. That’s the full starter loop. Next, try adding another entity (for example, Order) and a relationship. Or swap to SQL Server and point at a real instance.

I’m curious: where will you use this starter – console tool, API, or a background worker? Tell me in the comments and I’ll add the next steps for the most requested path.

Leave a Reply

Your email address will not be published. Required fields are marked *