# Skill 10 - EF Core Data Access ## Core Concepts - EF Core maps entity classes to relational database tables. - `DbContext` represents a unit of work and change tracker. - Providers translate LINQ expressions to database-specific SQL. - Database First starts from an existing database; Code First starts from C# models and migrations. ## DbContext Rules - Register `DbContext` with dependency injection using an appropriate lifetime, usually scoped for web apps. - Keep `DbContext` short-lived. - Do not share a `DbContext` across threads. - Use `AsNoTracking()` for read-only queries when tracking is not needed. - Use transactions when multiple changes must succeed or fail together. ## Entity Design Rules - Entities should protect important invariants, but EF also needs materialization support. - Avoid exposing EF entities directly from public APIs. - Keep navigation properties intentional. - Avoid lazy-loading surprises unless the project deliberately uses lazy loading. ## Query Rules - Filter in the database, not in memory. - Project only needed columns for read models and API responses. - Watch for N+1 query problems. - Use `Include` intentionally; do not include entire object graphs by habit. - Use pagination for large result sets. - Use async EF methods in web applications. ## Change Rules - Validate input before attaching or saving entities. - Handle concurrency where concurrent updates are possible. - Do not build SQL by string concatenation with untrusted input. - Use migrations deliberately and review generated migrations. ## Testing Rules - Use real providers for integration tests where SQL translation matters. - Avoid assuming the in-memory provider behaves like a relational database. ## Repository Pattern When the project uses a Unit of Work or generic repository abstraction, load `.ai/skills/18-unit-of-work-pattern.md` for rules on shared `DbContext` lifetime, repository staging, and single `SaveChangesAsync` per logical operation.