EFDoctor 0.3.0

dotnet tool install --global EFDoctor --version 0.3.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local EFDoctor --version 0.3.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=EFDoctor&version=0.3.0
                    
nuke :add-package EFDoctor --version 0.3.0
                    

EFDoctor

Local-first performance and safety diagnostics for EF Core codebases.

EFDoctor loads your solution with Roslyn and reports a small number of evidence-based findings, such as SaveChanges inside a loop, a query materialized before filtering, or an EF Core task that is never awaited. Each finding has a precise source location, a confidence level, the evidence that matched, the likely impact, and a practical fix. Nothing leaves your machine: there is no telemetry, network call, or source upload.

0.x. EFDoctor is usable today, but rules, options, and output may still change before 1.0.

Install

dotnet tool install --global EFDoctor

EFDoctor needs the .NET 10 runtime or later, and a .NET SDK that can build the project you analyze.

Run

Restore or build the target first, then:

efdoctor analyze path/to/App.sln
efdoctor analyze path/to/App.csproj --format json --quiet
Exit code Meaning
0 No findings
1 One or more findings
2 Invalid input or the target could not be analyzed

A project that uses EF Core but whose EF Core types don't resolve (not restored, or a failed design-time build) isn't analyzed, and EFDoctor warns about it on standard error. If no EF Core project resolves, the run exits with 2 instead of reporting a clean result.

Loading a project runs its MSBuild logic, so analyze only repositories you trust.

Rules

Rule Finding
EFD001 SaveChanges/SaveChangesAsync inside a loop
EFD002 Count/CountAsync used only to test existence
EFD003 Foreign key without a covering index in a SQL Server or PostgreSQL model snapshot
EFD004 Query materialized before filtering, projection, ordering, or paging
EFD005 ToList/ToListAsync without a recognized row bound
EFD006 Multiple sibling collection Includes that may cause cartesian explosion
EFD009 ToLower()/ToUpper() on a column in a predicate, which prevents an index seek
EFD010 Synchronous EF Core database call (ToList, Count, SaveChanges, Find, …) inside an async method
EFD011 .Result, .Wait(), or .GetAwaiter().GetResult() on an EF Core async call
EFD012 Dynamically built SQL passed to FromSqlRaw/ExecuteSqlRaw
EFD013 Load/loop/save pattern that may suit ExecuteUpdate/ExecuteDelete
EFD014 Skip pagination with no preceding OrderBy, producing non-deterministic pages
EFD017 Include ignored by a later non-entity Select
EFD018 EF Core async call whose task is discarded
EFD019 Query materialized and then immediately reduced, such as ToList().First()
EFD020 EF Core query enumerated more than once, re-running it each time
EFD021 EF Core DbContext held in a static field
EFD022 StringComparison overload in a query predicate that EF Core cannot translate
EFD023 Contains, EndsWith, or leading-wildcard Like on a column (advisory)
EFD025 Duplicate or already-covered Include path in the same query (Info)
EFD027 Concurrent EF Core operations on the same DbContext, such as Task.WhenAll over two queries
EFD029 Second OrderBy that discards an earlier ordering instead of ThenBy

Suppress an intentional finding with standard Roslyn mechanisms (#pragma warning disable EFD001, .editorconfig, or [SuppressMessage]) and record why.

License

Apache-2.0. See the NOTICE and THIRD-PARTY-NOTICES.md files included in the package.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.3.0 98 9/29/2026
0.2.0 81 9/28/2026

0.3.0: two new rules, for 22 in all. EFD027 reports EF Core operations running at once on the same DbContext instance, such as Task.WhenAll over two queries, which throws at run time. EFD029 reports a second OrderBy that discards an earlier ordering where ThenBy was meant. See CHANGELOG.md in the package.