Chapter 01 · EF Core Foundations, .NET Integration, Providers, and the First Lab

Install the CLI and Packages, Choose a Database Provider, and Verify the Toolchain

Install and verify the EF Core CLI, aligned project packages, and a relational provider as separate toolchain layers, then diagnose design-time failures with evidence instead of reinstalling blindly.

Intermediate90–110 minuteslocal dotnet-ef + provider verification labEF Core 10.0.11 · .NET 10SQLite 3.46.1+ baselineLast reviewed: August 2026

Learning outcomes

ServiceHub has a supported version contract; now it needs a toolchain that every developer and CI agent can reproduce. The goal is not “install some NuGet packages until IntelliSense turns green.” We will separate SDK tooling, the EF CLI tool, project design-time services, the relational provider, and the database engine, then verify each layer independently.

01

Install dotnet-ef as a repository-local tool and explain when a global installation is acceptable.

02

Add the EF Core Design package and a relational provider with aligned 10.0.11 versions.

03

Choose SQLite for the mandatory cross-platform lab while understanding when SQL Server, PostgreSQL, MySQL/MariaDB, or Oracle providers are appropriate.

04

Verify restore, build, runtime provider registration, and design-time tooling independently.

05

Diagnose missing Design-package, provider-registration, and version-drift failures without randomly reinstalling the SDK.

Course baseline

The mandatory first lab uses Microsoft.EntityFrameworkCore.Sqlite 10.0.11 with SQLite 3.46.1 or later. Microsoft’s provider documentation currently lists both SQLite and SQL Server providers for EF Core 10. Other provider ecosystems have independent schedules and must be checked against their own compatibility documentation before adoption.

1. The toolchain has five separate pieces

Piece Installed where Purpose
.NET 10 SDK Developer/CI machine Build, restore, templates, dotnet CLI and compilers
dotnet-ef Global tool store or repository tool manifest Design-time commands such as migrations and reverse engineering
Microsoft.EntityFrameworkCore.Design Project PackageReference Design-time services consumed by EF tooling
Database provider Project PackageReference Runtime + migration translation for a database family
Database engine/library Local file/process/container/server Actually executes SQL and enforces relational semantics

A failure in one piece does not imply the others are broken. For example, dotnet ef --version can succeed even when the startup project lacks Microsoft.EntityFrameworkCore.Design. Conversely, a project can compile and run normal EF queries without dotnet-ef installed because the CLI tool is not a runtime dependency.

2. Prefer a local dotnet-ef tool for repository reproducibility

A global tool is convenient on a personal workstation, but its version can drift independently from the repository. A local tool is declared in .config/dotnet-tools.json and restored with the repository. That makes CI and developer setup explicit.

text · create and verify a local EF CLI tool
dotnet new tool-manifestdotnet tool install dotnet-ef --version 10.0.11dotnet tool list --localdotnet ef --version

Commit the tool manifest, not a machine-specific tool cache. A new checkout can run dotnet tool restore. If an organization standardizes a global tool, record its required version and still verify it in CI; “global” should not mean “unknown.”

PMC is a different command surface

Visual Studio Package Manager Console commands such as Add-Migration are not the same syntax as dotnet-ef. This course prefers cross-platform dotnet CLI commands. PMC may be shown as an alternative when it adds value, but command sets will not be mixed.

3. Choose the provider from the production contract, not from LINQ familiarity

The provider determines database-specific type mappings, SQL generation, function translation, migrations operations, value generation, concurrency capabilities, and many diagnostics. Provider selection is therefore an architectural decision, not a cosmetic connection-string switch.

Provider path Good first use Boundary to remember
Microsoft.EntityFrameworkCore.Sqlite Cross-platform local labs, embedded applications, lightweight tests SQLite type affinity, DDL, concurrency, functions, and SQL semantics differ from server databases.
Microsoft.EntityFrameworkCore.SqlServer SQL Server/Azure SQL applications and provider-specific labs Requires a SQL Server-compatible engine; SQL Server-specific types/features are intentional lock-in.
Npgsql.EntityFrameworkCore.PostgreSQL PostgreSQL applications Independent provider release/support matrix; PostgreSQL types/functions and migrations differ.
MySQL/MariaDB providers MySQL or MariaDB applications Vendor/community providers have independent EF/database compatibility matrices.
Oracle.EntityFrameworkCore Oracle Database applications Vendor provider, database versions, feature support, and deployment/licensing assumptions must be checked.

SQLite is the mandatory Chapter 01 provider because it is free and requires no server process. That does not make SQLite a universal stand-in for a production SQL Server or PostgreSQL database. Chapter 23 explains why provider-realistic integration tests matter.

4. Add aligned project packages

Create the project with the course target framework, then add the provider and design-time package at the same EF patch. Explicit versions make the lab reproducible even if a newer servicing patch is released later.

text · project and packages
dotnet new console -n ServiceHub.EfLab -f net10.0cd ServiceHub.EfLabdotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 10.0.11dotnet add package Microsoft.EntityFrameworkCore.Design --version 10.0.11dotnet restoredotnet builddotnet list package

The SQLite provider pulls the relational/core packages it needs. Inspect the resolved package graph rather than adding every EF package you have heard of. Microsoft.EntityFrameworkCore.Tools is for Visual Studio Package Manager Console; it is not required just because you use dotnet ef.

5. Verify runtime provider registration separately from tooling

A provider package being present does not configure a DbContext. EF Core needs provider services registered in the context options. For the first probe, build options directly and inspect the provider name.

csharp · runtime provider probe
using Microsoft.EntityFrameworkCore;var options = new DbContextOptionsBuilder<ProbeContext>()    .UseSqlite("Data Source=toolchain-probe.db")    .Options;await using var context = new ProbeContext(options);Console.WriteLine(context.Database.ProviderName);public sealed class ProbeContext(DbContextOptions<ProbeContext> options)    : DbContext(options);

dotnet run should print Microsoft.EntityFrameworkCore.Sqlite. This proves that the built application can construct an EF context with SQLite provider services. It does not prove migrations tooling can construct the context at design time; that is a separate path.

6. Deliberately wrong approach: run migrations without the Design package

Remove or omit Microsoft.EntityFrameworkCore.Design, then ask the EF tool to perform a project-aware design-time operation. The tool can exist and report its own version, yet the project is missing the services it needs.

text · intentional design-time failure
dotnet remove package Microsoft.EntityFrameworkCore.Designdotnet ef migrations add ToolchainProbe

The exact diagnostic text can change across patches, but it should explain that the startup project does not reference Microsoft.EntityFrameworkCore.Design or otherwise cannot provide required design-time services. The repair is explicit:

text · repair the project design-time dependency
dotnet add package Microsoft.EntityFrameworkCore.Design --version 10.0.11dotnet restoredotnet build

Do not respond by reinstalling Visual Studio, deleting every NuGet cache, or installing random global tools. First identify which layer failed: CLI discovery, project restore, build, design-time context creation, provider loading, or database connection.

7. Another common failure: package installed, UseSqlite unavailable

If UseSqlite is unresolved, inspect the provider PackageReference and the using Microsoft.EntityFrameworkCore; namespace before assuming the database is broken. If the compiler error appears only on one machine, compare the resolved package graph and target framework. Compile-time provider-extension discovery occurs before any connection to SQLite.

text · evidence before cleanup
dotnet --versiondotnet restoredotnet builddotnet list package --include-transitivedotnet tool list --local

8. Design-time context creation is an application-construction problem

Commands such as dotnet ef migrations add need a DbContext instance at design time. In real applications EF tooling may obtain it through the application service provider, a parameterless construction path, or an IDesignTimeDbContextFactory<TContext>. Chapter 2 teaches those patterns in detail. For now, recognize the symptom: a successful build followed by “Unable to create a DbContext” is not the same failure as a missing tool or provider.

Record the full exception and startup-project/target-project selection. Multi-project solutions frequently fail because tooling executes a different startup path than the developer expected.

9. Observe provider SQL with a one-row query

Toolchain verification is stronger when it reaches the database. The following disposable probe creates a SQLite database, inserts one row, then prints the generated query text. EnsureCreated is used only as a prototype probe; migrations become the normal course schema lifecycle beginning in Lesson 4/Chapter 15.

csharp · provider execution probe
using Microsoft.EntityFrameworkCore;var options = new DbContextOptionsBuilder<ProbeContext>()    .UseSqlite("Data Source=toolchain-probe.db")    .LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information)    .Options;await using var db = new ProbeContext(options);await db.Database.EnsureDeletedAsync();await db.Database.EnsureCreatedAsync();db.Items.Add(new ProbeItem { Name = "provider-ok" });await db.SaveChangesAsync();var query = db.Items.Where(x => x.Name == "provider-ok");Console.WriteLine(query.ToQueryString());Console.WriteLine(await query.CountAsync());public sealed class ProbeContext(DbContextOptions<ProbeContext> options) : DbContext(options){    public DbSet<ProbeItem> Items => Set<ProbeItem>();}public sealed class ProbeItem{    public int Id { get; set; }    public string Name { get; set; } = "";}

Expected evidence includes provider command logs, a SQLite-style quoted table/column query, and a result count of one. Exact command formatting is provider/patch dependent. Treat the output as observed behavior from your declared environment, not universal SQL text.

10. Hands-on lab: build the repository-local toolchain from zero

text · complete toolchain sequence
mkdir ServiceHubEfCoursecd ServiceHubEfCoursedotnet new globaljson --sdk-version 10.0.400 --roll-forward latestPatchdotnet new tool-manifestdotnet tool install dotnet-ef --version 10.0.11dotnet new console -n ServiceHub.EfLab -f net10.0cd ServiceHub.EfLabdotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 10.0.11dotnet add package Microsoft.EntityFrameworkCore.Design --version 10.0.11dotnet restoredotnet buildcd ..dotnet tool restoredotnet ef --version

Verification checklist

  • global.json and .config/dotnet-tools.json exist at the repository root.
  • dotnet --version resolves according to the repository SDK policy.
  • dotnet ef --version reports 10.0.11.
  • The project targets net10.0 and resolves SQLite/Design 10.0.11.
  • dotnet build succeeds before any database command is attempted.
  • A runtime probe reports Microsoft.EntityFrameworkCore.Sqlite.
  • You can explain why missing Design services is different from a provider package or database-connection failure.

Check your understanding

  1. Why can dotnet ef --version succeed while dotnet ef migrations add fails?
  2. What benefit does a local tool manifest provide over an unpinned global dotnet-ef?
  3. Why is SQLite the Chapter 01 baseline but not a promise of provider portability?
  4. Do you need Microsoft.EntityFrameworkCore.Tools to use dotnet-ef?
  5. What should you inspect before deleting NuGet caches in response to an EF tooling failure?
Review the answers

The CLI tool can be installed correctly while the project lacks Design services, fails to build, or cannot construct a DbContext at design time.

The manifest records the tool/version with the repository so developers and CI can restore the same CLI instead of depending on machine-global state.

It is free and cross-platform, but its type system, DDL, functions, locking, and SQL differ from other engines; provider-specific behavior must be tested separately.

No. Microsoft.EntityFrameworkCore.Tools is for Visual Studio Package Manager Console. dotnet-ef uses the .NET CLI tool plus Microsoft.EntityFrameworkCore.Design in the project.

Inspect SDK/target framework, restore/build diagnostics, direct/transitive packages, tool version/location, design-time context creation, and provider registration first.

11. Production judgment and next bridge

Toolchain reproducibility is a supply-chain and operations concern. Pin what must be reproducible, restore packages/tools from approved sources, patch supported components deliberately, and keep project/runtime/design-time responsibilities separate. For provider adoption, evaluate maintainer, license, support, EF major compatibility, database versions, and the behaviors your application actually uses.

Nothing in this lesson requires a paid database or IDE. SQL Server, PostgreSQL, MySQL/MariaDB, and Oracle will appear when their semantics matter, but the mandatory path remains free/local. Lesson 4 now uses this verified SQLite toolchain to build the first real ServiceHubContext, migration, insert, LINQ query, SaveChangesAsync, and generated-SQL inspection.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.

\n