Skip to content

Repository files navigation

EFQueryGuard

A Roslyn analyzer that catches EF Core performance traps at compile time.

EF Core performance problems — N+1 queries, missing AsNoTracking(), unbounded queries, cartesian explosions, and synchronous database calls in async contexts — are among the most common .NET issues. EFQueryGuard detects these patterns during compilation with clear diagnostics and suggested fixes.

Installation

dotnet add package EFQueryGuard

That's it. The analyzer runs automatically during build with zero configuration.

Diagnostics

IDSeverityDescription
EFQ001WarningNavigation property accessed in loop without Include() — causes N+1 queries
EFQ002InfoRead-only query missing AsNoTracking()
EFQ003WarningUnbounded query without Take() or pagination
EFQ004WarningMultiple collection Include() calls cause cartesian explosion
EFQ005WarningSynchronous query method in async method
EFQ006InfoExpression may trigger client-side evaluation

Examples

EFQ001 — N+1 Query Detection

// Warning: Navigation 'Order.Items' accessed in loop without Include()foreach(varorderinctx.Orders.ToList()){varitems=order.Items;// N+1! Each iteration hits the database}// Fix: add Include()foreach(varorderinctx.Orders.Include(o =>o.Items).ToList()){varitems=order.Items;// OK — loaded eagerly}

EFQ002 — Missing AsNoTracking

// Info: Read-only query on 'Products' missing AsNoTracking()varproducts=ctx.Products.Where(p =>p.Active).ToList();// Fix:varproducts=ctx.Products.AsNoTracking().Where(p =>p.Active).ToList();

EFQ003 — Unbounded Query

// Warning: Unbounded query on 'Products' — add Take() or paginationvarall=ctx.Products.ToList();// Fix:varpage=ctx.Products.Take(100).ToList();

EFQ004 — Cartesian Explosion

// Warning: Multiple Include() calls on 'Orders' may cause cartesian explosionvarorders=ctx.Orders.Include(o =>o.Items).Include(o =>o.Notes).ToList();// Fix: use AsSplitQuery()varorders=ctx.Orders.Include(o =>o.Items).Include(o =>o.Notes).AsSplitQuery().ToList();

EFQ005 — Sync over Async

// Warning: Synchronous call 'ToList' in async method — use 'ToListAsync'publicasyncTask<List<Product>>GetProducts(TestContextctx){returnctx.Products.ToList();// blocks the thread!}// Fix:publicasyncTask<List<Product>>GetProducts(TestContextctx){returnawaitctx.Products.ToListAsync();}

EFQ006 — Client Evaluation

// Info: Call to 'IsValid' may trigger client-side evaluationvarproducts=ctx.Products.Where(p =>IsValid(p.Name)).ToList();// Fix: use inline expression or EF-translatable methodsvarproducts=ctx.Products.Where(p =>p.Name.Length>3).ToList();

Configuration

Suppress individual rules via .editorconfig:

[*.cs]dotnet_diagnostic.EFQ001.severity = none
dotnet_diagnostic.EFQ002.severity = warning

Or suppress inline:

#pragma warning disable EFQ003varall=ctx.Products.ToList();
#pragma warning restore EFQ003

Supported EF Core Versions

EF Core 6, 7, 8, and 9. The analyzer detects patterns based on type names and method signatures, so it works across all supported versions.

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for any new diagnostics
  4. Ensure dotnet test passes with zero failures
  5. Submit a pull request

Development

dotnet build # Build all
dotnet test# Run tests
dotnet build --no-incremental # Clean build
dotnet format # Format code

License

MIT

About

Roslyn analyzer that catches EF Core performance traps at compile time

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages