Entity Framework Core maps classes to tables and LINQ to SQL. That is the whole promise, and most of the difficulty is in the two places the abstraction is thin: what SQL your query actually becomes, and what the change tracker thinks it is holding.

The sections below start with the model, move through migrations and querying, and end with performance and the cases where a micro ORM or plain SQL is the better tool. Dapper gets real space here rather than a footnote, because the honest answer to “EF Core or Dapper” is often both, in different parts of the same application.

Other databases live here too. MongoDB, Redis, Elasticsearch and PostgreSQL are all data access, and splitting them onto another page would only make them harder to find.

Getting Started

Wiring EF Core into an application for the first time, from both directions: model first and database first.

Modelling and Relationships

Turning classes into a schema, which is where most of the decisions you cannot easily undo get made.

Migrations

Changing a schema that already has data in it.

Querying and Loading

Reading and writing, and seeing the SQL that comes out before it surprises you in production.

DbContext, Interceptors and Lifetime

The object that holds the connection and the change tracker, and the trouble it causes when its lifetime is wrong.

Dapper and Raw SQL

When you want the query you wrote rather than the query an ORM composed.

Other Databases and Stores

Everything that is not a relational database with EF Core in front of it.

Testing and Best Practices

Proving the data layer works without a production database, and the habits that keep it fast.

Where to Go Next

The application around the data layer:

Turn on SQL logging in development and leave it on. Nearly every EF Core performance surprise is visible the first time you read the query it generated.