EF Core Interview Questions for Senior .NET Developers (2026)

EF Core interview questions for senior .NET developers are fundamentally different from beginner-level quizzes. At the senior level, interviewers are probing for architectural judgment, performance awareness, and hard-won production experience โ not just the ability to recall what DbContext does. This guide covers the questions that consistently surface in senior .NET interviews in 2026, grouped by difficulty and organized to help you build a coherent mental model across the EF Core feature surface.
๐ Want implementation-ready .NET source code you can drop straight into your project? Join Coding Droplets on Patreon for exclusive tutorials, premium code samples, and early access to new content. ๐ https://www.patreon.com/CodingDroplets
What Do Senior EF Core Interview Questions Actually Test?
Interviewers hiring at the senior level are not looking for recitation. They want to understand whether you have built something real with EF Core, hit its limits, and made deliberate choices about when to use it and when to step around it. The questions below reflect that intent.
Expect interviewers to follow up any answer with "why?" or "what would go wrong if you didn't?" That pressure is deliberate โ it separates developers who have read the docs from developers who have been paged at 2 AM because of N+1 queries in production.
Basic-Level Questions
What Is the Role of DbContext in EF Core?
DbContext is the central unit-of-work and identity map in EF Core. It manages the lifecycle of entity tracking, coordinates change detection, and exposes DbSet<T> properties that represent the query surface for each entity. A DbContext instance is scoped to a unit of work โ typically a single HTTP request in ASP.NET Core โ and should never be shared across threads.
The key things to articulate in an interview: it is not thread-safe, its lifetime matters for correctness, and instantiating it incorrectly (e.g., as a singleton) will cause tracking bugs and memory leaks.
What Is the Difference Between Eager, Lazy, and Explicit Loading?
| Loading Strategy | Mechanism | When SQL Runs |
|---|---|---|
| Eager Loading | .Include() / .ThenInclude() |
At query time โ one query or join |
| Lazy Loading | Virtual navigation properties + proxy | On first access of the navigation |
| Explicit Loading | context.Entry(entity).Collection(...).LoadAsync() |
When you call Load explicitly |
Senior developers should know that lazy loading is disabled by default in EF Core and requires either proxies or the Microsoft.EntityFrameworkCore.Proxies package. More importantly, they should be able to explain why lazy loading is dangerous in web APIs: it silently generates N+1 queries unless carefully managed, making it a frequent source of production performance incidents.
What Is Change Tracking and When Does It Matter?
EF Core's change tracker monitors every entity returned by a tracked query. When SaveChanges() is called, it computes a diff between the original snapshot and the current entity state, then generates the appropriate INSERT, UPDATE, or DELETE statements.
Change tracking has a real cost. For read-only queries โ reports, list endpoints, API GET responses โ using .AsNoTracking() eliminates that overhead entirely. For large result sets, the performance difference can be significant. Senior developers know to use AsNoTracking() by default on read paths and only enable tracking when they need to persist changes.
Intermediate-Level Questions
How Does EF Core Handle Migrations in a Multi-Instance Production Environment?
This is a trap question for less experienced developers, who often answer: "call database.MigrateAsync() at startup." That approach is dangerous in production. When multiple application instances start simultaneously, they all attempt to apply migrations concurrently, leading to race conditions, deadlocks, and failed deployments.
The correct approach depends on your deployment model:
- Dedicated migration job or init container โ run migrations as a separate step before application startup, not inside the application itself.
MigrationRunnertools like Flyway or Liquibase in environments where EF Core migrations are not the right fit.- Azure SQL / RDS maintenance windows where migrations are applied by a CI/CD pipeline as a deployment gate.
- Distributed locks if you must use EF Core migrations at startup โ acquire a database-level advisory lock so only one instance proceeds.
The interviewer is looking for awareness that MigrateAsync() at startup is not production-safe at scale.
What Is the N+1 Query Problem and How Do You Detect It?
The N+1 problem occurs when a query returns N entities, and then for each entity, a separate query is issued to load a related navigation property. The result is 1 + N database round trips instead of 1.
In EF Core, N+1 typically emerges from:
- Forgetting
.Include()on a navigation property you access in a loop - Accessing lazy-loaded navigation properties inside a
foreach - Projecting into a type but accessing navigations outside the projection
Detection in development: Enable EF Core query logging via LogTo on DbContextOptionsBuilder. Each SQL statement is logged โ if you see 50+ nearly identical queries for a single request, that is N+1.
Detection in production: Use a telemetry backend like Application Insights or Datadog with SQL trace enabled. Tools like MiniProfiler expose query counts per HTTP request in the developer toolbar.
How Do You Optimize a Slow EF Core Query?
Senior candidates should be able to describe a systematic approach:
- Log and measure first. Never optimize blindly. Use
LogTo, MiniProfiler, or a tracing backend to see the actual SQL being generated. - Check the execution plan. Paste the generated SQL into SSMS or
EXPLAIN(Postgres). Look for table scans, missing indexes, or join explosions. - Add
.AsNoTracking()on read paths if not already present. - Switch to a projection. Instead of loading full entities and navigations, use
.Select()to project to a DTO. EF Core will only generate columns you actually need. - Consider compiled queries for hot paths.
EF.CompileQuery()eliminates LINQ expression tree compilation overhead on repeated calls. - Consider raw SQL or Dapper for complex reporting queries where the ORM generates poor SQL. EF Core's
FromSqlRaworFromSqlInterpolatedallow you to mix raw SQL with tracked entities.
What Are Shadow Properties and When Would You Use Them?
Shadow properties are entity properties that exist in the EF Core model and the database schema but not on the C# entity class. They are configured in OnModelCreating via the Fluent API.
Common use cases:
- Audit fields (
created_at,updated_at,created_by) that you want in the database but don't want polluting your domain entities. - Foreign key columns that should not be exposed on the entity itself.
- Soft-delete flags (
deleted_at) for entities that need tombstoning without changing the entity surface.
Shadow property values are set and read via context.Entry(entity).Property("PropertyName").CurrentValue.
Advanced-Level Questions
How Would You Implement a Global Query Filter for Soft Deletes and Multi-Tenancy?
EF Core's global query filters allow you to define a WHERE condition that is automatically appended to every query for a given entity type. They are configured in OnModelCreating:
modelBuilder.Entity<Order>().HasQueryFilter(o => !o.IsDeleted && o.TenantId == _tenantId);
For multi-tenancy, _tenantId is typically injected via a scoped service that resolves the current tenant from the HTTP request (a claims-based tenant resolver, for example). The DbContext constructor receives the tenant resolver, which captures the tenant identifier into a field used by the filter expression.
Key production considerations:
- Filters are applied at the EF Core level, not the database level โ they do not replace row-level security for truly sensitive isolation.
- Filters can be bypassed per-query using
.IgnoreQueryFilters(). This is useful for admin operations or cross-tenant queries but must be deliberate and audited. - Filter expressions are compiled into the query tree. Complex expressions with captured closures can cause unexpected behavior if the closure value changes after filter registration.
What Is the Difference Between DbContext Pooling and DbContext as a Scoped Service?
In standard ASP.NET Core DI, DbContext is registered as Scoped, meaning one instance is created and destroyed per HTTP request. This works correctly but has overhead: every request allocates a new DbContext, establishes a connection from the pool, and then disposes both.
DbContext pooling (AddDbContextPool) reuses DbContext instances across requests. When a request completes, the context is reset (tracking cleared, configuration preserved) and returned to a pool rather than disposed. For high-throughput APIs, this can reduce allocation pressure and GC load meaningfully.
The trade-off: the DbContext reset process only clears tracked entities and query-level state. Any instance-level state you store on a custom DbContext subclass will NOT be reset automatically. If your DbContext subclass holds mutable state (tenant ID, user ID captured via constructor injection), you must override OnConfiguring or use a factory approach instead of pooling directly.
How Does EF Core's Connection Resiliency Work and When Should You Configure It?
Connection resiliency enables automatic retry on transient failures. You configure it per database provider:
- SQL Server:
EnableRetryOnFailure()onUseSqlServerโ uses exponential backoff by default - Postgres (Npgsql):
EnableRetryOnFailure()onUseNpgsql - Azure SQL: Essential โ Azure SQL enforces connection limits and can issue transient errors under load
The critical constraint: retries are not safe inside a user-managed transaction. If you call BeginTransaction() manually, you must disable retries or implement a retry execution strategy that is aware of the transaction boundary. EF Core will throw InvalidOperationException if you attempt to use the retry strategy inside a manually started transaction without wrapping it in an execution strategy block.
Refer to the Microsoft Docs on connection resiliency in EF Core for the execution strategy pattern used with manual transactions.
How Would You Handle Concurrency Conflicts in EF Core?
EF Core supports optimistic concurrency via rowversion/timestamp columns or concurrency tokens. When SaveChanges is called and the row version in the database does not match the version the entity was loaded with, EF Core throws DbUpdateConcurrencyException.
Handling strategies:
- Client wins: Re-read database values, overwrite with client values, save again.
- Database wins: Reload entity from database, discard client changes.
- Merge: Read both versions, apply a merge strategy, save the result.
- Fail loudly: Propagate the exception to the caller as a
409 ConflictHTTP response. This is the correct approach for most APIs โ surface the conflict to the consumer and let them decide.
The DbUpdateConcurrencyException exposes Entries which contains the conflicting EntityEntry objects. Each entry exposes OriginalValues, CurrentValues, and GetDatabaseValues() (async) โ the raw materials for any merge strategy.
Architecture-Level Questions
When Should You NOT Use EF Core?
This is a question designed to test whether a senior developer has a clear-eyed view of tooling trade-offs rather than being an ORM advocate.
Avoid EF Core (or complement it with raw SQL/Dapper) when:
- You are writing complex reporting or analytics queries โ EF Core's SQL generation can produce suboptimal query plans for multi-table aggregations.
- You need fine-grained control over query structure (specific index hints, CTEs, window functions) โ
FromSqlRawbecomes necessary and at that point you are essentially writing raw SQL anyway. - You are working with high-volume write paths where change tracking overhead is measurable and not justified.
- Your schema does not map cleanly to objects (legacy databases with composite keys, denormalized schemas, stored procedure-heavy architectures).
The right answer acknowledges EF Core's value while recognizing its limits. Developers who say "just use Dapper for everything" or "EF Core is always fine" both miss the mark.
How Do You Organize EF Core Configuration in a Large Codebase?
Large codebases should not inline entity configuration in OnModelCreating. The standard pattern is to use IEntityTypeConfiguration<T>:
public class OrderConfiguration : IEntityTypeConfiguration<Order> { ... }
And register all configurations in one call:
modelBuilder.ApplyConfigurationsFromAssembly(typeof(YourDbContext).Assembly);
This keeps each entity's mapping isolated in its own file, makes navigation straightforward, and eliminates the god-method OnModelCreating that becomes a merge conflict magnet in team development.
Senior developers should also understand the difference between the Data Annotation approach and Fluent API: Fluent API always wins when both are present, and for enterprise codebases, Fluent API is almost always preferred because it keeps domain entities free of infrastructure concerns.
FAQ
What Are the Most Common EF Core Performance Mistakes in Production?
The most frequent mistakes are: missing .AsNoTracking() on read paths, N+1 queries from lazy loading or missing .Include(), loading full entities when a projection would do, and applying database migrations inside application startup in multi-instance deployments.
What Is the Difference Between First() and FirstOrDefault() in EF Core Queries?
First() throws InvalidOperationException if no result is found. FirstOrDefault() returns the default value (null for reference types) if no result matches. In API code, FirstOrDefault() is generally preferred because it allows you to handle the not-found case explicitly rather than catching an exception. Use First() only when the absence of a result is truly unexpected and represents a programming error.
Should You Use EF.CompileQuery() for All Queries?
No. Compiled queries eliminate LINQ expression tree compilation overhead, but they introduce constraints: parameters must match the delegate signature, and the query cannot be dynamically composed. They are worth the investment only for hot paths โ queries executed hundreds or thousands of times per second where profiling shows expression compilation is a measurable overhead.
How Do You Unit Test Code That Uses EF Core?
The recommended approach is to use the EF Core in-memory provider (UseInMemoryDatabase) for lightweight unit tests or SQLite in-memory mode for tests that need relational behavior (constraints, foreign keys). For integration tests that need realistic SQL semantics, use Testcontainers to spin up a real database instance in a Docker container. Each approach has different trade-offs between speed, fidelity, and infrastructure complexity.
What Is the Difference Between a Migration and a Seed in EF Core?
Migrations define schema changes โ adding tables, columns, indexes, constraints. Seeds populate reference data or initial rows. EF Core's HasData() in OnModelCreating embeds seed data into migrations, which means seed data changes generate new migration files. For large or frequently changing reference data, managing seeds outside of EF Core migrations (e.g., via a dedicated seed script run by the CI/CD pipeline) is usually more maintainable.
How Does SaveChanges() Handle Transactions?
By default, SaveChanges() wraps all changes in a single database transaction. Either all changes commit or all roll back. If you need finer control โ for example, to include non-EF operations in the same transaction โ you can use context.Database.BeginTransaction() to manage the transaction boundary manually and call SaveChanges() within it.
Is EF Core Suitable for Microservices?
Yes, with caveats. In a microservices architecture, each service owns its own database and its own DbContext. EF Core is well-suited for this because the bounded context model aligns naturally with the ORM's entity ownership model. The concern is not EF Core itself but rather using a single DbContext to span data across service boundaries โ which is an anti-pattern regardless of the ORM used.
โ Prefer a one-time tip? Buy us a coffee โ every bit helps keep the content coming!
Preparing for a senior .NET role means going beyond syntax recall and into the territory of architectural reasoning. The EF Core questions above reflect what hiring managers at product companies and consulting firms are actually asking in 2026. If you want to sharpen your practical instincts further, visit Coding Droplets for more deep-dive content on ASP.NET Core and .NET architecture.




