Rule reference

LinqContraband Rule Catalog

Full LinqContraband EF Core analyzer rule catalog grouped by query, materialization, loading, async, tracking, raw SQL, and schema design.

The source of truth for rule metadata lives in src/LinqContraband/Catalog/RuleCatalog.cs. This page is generated from that catalog and grouped by EF Core failure mode.

63rules
44warnings
46code fixes

8 diagnostic domains

Bulk Operations & Set-Based Writes

Keep destructive and high-volume writes set-based while making the risky cases explicit.

Change Tracking & Context Lifetime

Spot DbContext lifetime leaks, tracking-mode surprises, and writes that silently do nothing.

LC009 Info

Performance: Missing AsNoTracking() in Read-Only path

Suggests AsNoTracking() for read-only EF Core queries, so the change tracker does not snapshot entities the code never modifies.

Performance Code fix Samples/LC009_MissingAsNoTracking/
LC010 Warning

N+1 Write Problem: SaveChanges inside loop

Flags SaveChanges or SaveChangesAsync inside a loop, which costs one database round trip per item instead of one batched save.

Performance Code fix Samples/LC010_SaveChangesInLoop/
LC013 Warning

Disposed Context Query

Detects an IQueryable or IAsyncEnumerable returned after its DbContext is disposed, which throws when the caller finally enumerates it.

Reliability Manual only Samples/LC013_DisposedContextQuery/
LC025 Warning

Avoid AsNoTracking with Update/Remove

Detects entities loaded with AsNoTracking() and then passed to Update or Remove, which can overwrite every column or fail on identity conflicts.

Reliability Code fix Samples/LC025_AsNoTrackingWithUpdate/
LC030 Info

Potential DbContext lifetime mismatch

Flags singletons and hosted services that store a DbContext, a lifetime mismatch that leads to threading errors and stale data. Use a factory.

Architecture Manual only Samples/LC030_DbContextInSingleton/
LC039 Info

Avoid repeated SaveChanges on the same context

Flags repeated SaveChanges calls on the same DbContext in one method, which add round trips and can leave partial writes. Save once.

Reliability Manual only Samples/LC039_NestedSaveChanges/
LC040 Info

Avoid mixing tracking modes on the same context

Flags methods that mix tracked and AsNoTracking() queries on the same DbContext, which makes later update behavior hard to predict.

Reliability Manual only Samples/LC040_MixedTrackingAndNoTracking/
LC044 Warning

AsNoTracking query mutated then SaveChanges — silent data loss

Detects entities loaded with AsNoTracking(), modified, then followed by SaveChanges, which silently saves nothing: data loss with no error.

Reliability Manual only Samples/LC044_AsNoTrackingThenModify/
LC048 Warning

Tracked update can overwrite a concurrent change

Detects tracked EF Core read-modify-write updates, such as counters, saved without a concurrency token, so concurrent requests overwrite each other.

Reliability Manual only Samples/LC048_LostUpdateRisk/
LC059 Warning

Connection owned by the DbContext is disposed

Flags code that disposes the connection from EF Core GetDbConnection(), which the DbContext owns, breaking later queries and SaveChanges.

Reliability Code fix Samples/LC059_DisposedContextConnection/

Execution & Async

Find synchronous calls, repeated database execution, and async paths that drop cancellation or buffer too early.

LC007 Warning

N+1 Problem: Database execution inside loop

Finds EF Core N+1 queries: Find, ToList, Count and other database calls that provably run once per loop iteration instead of once.

Performance Code fix Samples/LC007_NPlusOneLooper/
LC008 Warning

Sync-over-Async: Synchronous EF Core method in Async context

Flags synchronous EF Core calls such as ToList or SaveChanges inside async methods, where they block threads. Use the Async counterpart.

Performance Code fix Samples/LC008_SyncBlocker/
LC026 Info

Missing CancellationToken in async call

Flags EF Core async calls that omit an available CancellationToken, so cancelled requests keep running queries against the database.

Reliability Code fix Samples/LC026_MissingCancellationToken/
LC036 Warning

DbContext captured by thread work item

Detects one DbContext captured by Task.Run, Parallel.ForEach, threads or timers. DbContext is not thread-safe, so use one context per task.

Safety Manual only Samples/LC036_DbContextCapturedAcrossThreads/
LC043 Info

Prefer await foreach over buffering async streams

Flags an IAsyncEnumerable buffered with ToListAsync or ToArrayAsync only to loop over it once. Use await foreach to stream instead.

Performance Code fix Samples/LC043_AsyncEnumerableBuffering/
LC046 Warning

Concurrent EF Core operations on the same DbContext

Detects overlapping async operations on the same DbContext instance, which EF Core rejects at runtime. Await each call or use separate contexts.

Safety Manual only Samples/LC046_ConcurrentDbContextOperations/
LC051 Warning

ToAsyncEnumerable() runs an EF Core query synchronously

Flags ToAsyncEnumerable() on EF Core queries, which enumerates them synchronously and blocks a thread per row, and switches to AsAsyncEnumerable().

Performance Code fix Samples/LC051_ToAsyncEnumerableOnQuery/
LC058 Warning

TransactionScope without async flow spans an await

Flags a TransactionScope created without TransactionScopeAsyncFlowOption.Enabled in async code, where the transaction is lost after an await.

Reliability Code fix Samples/LC058_TransactionScopeWithoutAsyncFlow/
LC060 Warning

EF Core async operator on an in-memory query

Flags EF Core ToListAsync, CountAsync and other async operators on AsQueryable() over an in-memory collection, which throw at run time.

Reliability Code fix Samples/LC060_AsyncOnInMemoryQuery/
LC062 Warning

Blocking on an EF Core async call

Flags .Result, .Wait() and .GetAwaiter().GetResult() on EF Core async calls, which starve the thread pool and deadlock under a SynchronizationContext.

Performance Code fix Samples/LC062_BlockingEfAsyncCall/
LC063 Warning

User transaction under a retrying execution strategy

Flags BeginTransaction on an EF Core context set up with EnableRetryOnFailure, which throws unless the transaction runs in the execution strategy.

Reliability Code fix Samples/LC063_TransactionUnderRetryingStrategy/

Loading & Includes

Make relationship loading deliberate before N+1 round trips or over-eager include graphs reach production.

LC006 Warning

Cartesian Explosion Risk: Multiple Collection Includes

Detects sibling collection Include paths without AsSplitQuery(), where EF Core joins them into a Cartesian product that multiplies the rows returned.

Performance Code fix Samples/LC006_CartesianExplosion/
LC019 Warning

Conditional Include Expression

Flags ternary and null-coalescing expressions inside EF Core Include paths, which cannot translate. Apply the Include conditionally instead.

Correctness Manual only Samples/LC019_ConditionalInclude/
LC028 Warning

Deep ThenInclude Chain

Flags EF Core ThenInclude chains deeper than the configured limit, which load large object graphs. Project or split the query instead.

Performance Manual only Samples/LC028_DeepThenInclude/
LC038 Info

Avoid excessive eager loading

Flags EF Core queries with more Include and ThenInclude steps than the configured threshold, which load oversized graphs in one query.

Performance Manual only Samples/LC038_ExcessiveEagerLoading/
LC042 Info

Complex query should be tagged

Flags complex EF Core queries without TagWith() or TagWithCallSite(), so the SQL they produce is hard to trace back to code in logs.

Performance Code fix Samples/LC042_MissingQueryTags/
LC045 Warning

Missing Include: navigation accessed on materialized entity

Detects navigation properties read after an EF Core query without a matching Include, causing N+1 lazy loads or null and empty data.

Reliability Code fix Samples/LC045_MissingInclude/
LC049 Info

Include is ignored by a Select projection

Flags EF Core Include calls that a later Select projection makes EF Core ignore, and removes them.

Performance Code fix Samples/LC049_IncludeIgnoredByProjection/

Materialization & Projection

Keep work in SQL where it belongs and avoid loading whole entities or unbounded result sets by accident.

LC002 Warning

Premature query continuation after materialization

Catches ToList, ToArray or AsEnumerable before Where, Select or OrderBy, which moves EF Core query work out of SQL and into memory.

Performance Code fix Samples/LC002_PrematureMaterialization/
LC003 Warning

Prefer Any() over Count() existence checks

Flags Count() > 0 style existence checks on EF Core queries and suggests Any() or AnyAsync(), which can stop at the first matching row.

Performance Code fix Samples/LC003_AnyOverCount/
LC017 Info

Performance: Consider using Select() projection

Flags EF Core queries that load whole entities when only a few properties are used. Project with Select to fetch just the needed columns.

Performance Code fix Samples/LC017_WholeEntityProjection/
LC022 Info

Nested collection materialization inside projection

Flags ToDictionary on a nested collection in an EF Core Select projection, which throws, and nested ToList on EF Core 7 or older.

Performance Code fix Samples/LC022_ToListInSelectProjection/
LC023 Info

Use Find/FindAsync for primary key lookups

Suggests Find or FindAsync when FirstOrDefault or SingleOrDefault looks up an EF Core entity by primary key, so tracked entities skip the database.

Performance Code fix Samples/LC023_FindInsteadOfFirstOrDefault/
LC029 Info

Redundant identity Select

Flags Select(x => x) in LINQ and EF Core query chains. The identity projection does nothing and only adds noise to the expression tree.

Performance Code fix Samples/LC029_RedundantIdentitySelect/
LC031 Info

Unbounded Query Materialization

Flags EF Core queries materialized with no filter or Take limit, which can load an entire table into memory as the data grows.

Performance Manual only Samples/LC031_UnboundedQueryMaterialization/
LC033 Info

Use FrozenSet for provably read-only membership caches

Flags private static readonly HashSet lookup caches that are never mutated and suggests FrozenSet on .NET 8+ for faster membership checks.

Performance Code fix Samples/LC033_UseFrozenSetForStaticMembershipCaches/
LC041 Info

Single entity query over-fetches one consumed property

Flags First or Single queries that load a whole EF Core entity when only one property is read. Select that property to fetch one column.

Performance Code fix Samples/LC041_SingleEntityScalarProjection/
LC057 Warning

Min, Max or Average throws on an empty query

Flags EF Core Min, Max and Average over a non-nullable value, which throw 'Sequence contains no elements' when no row matches.

Reliability Code fix Samples/LC057_EmptyQueryAggregate/

Query Shape & Translation

Catch LINQ patterns that EF Core cannot translate reliably or cannot page deterministically.

LC001 Warning

Client-side evaluation risk: Local method usage in IQueryable

Flags your own helper methods inside EF Core IQueryable lambdas that SQL cannot translate, which forces client-side evaluation or a runtime error.

Performance Code fix Samples/LC001_LocalMethod/
LC004 Warning

Deferred Execution Leak: IQueryable passed as IEnumerable

Detects an EF Core IQueryable passed as IEnumerable to a method that enumerates it, so filtering runs in memory instead of in SQL.

Performance Code fix Samples/LC004_IQueryableLeak/
LC005 Warning

Multiple OrderBy calls

Flags a second OrderBy or OrderByDescending in one LINQ chain, which silently discards the first sort. Use ThenBy or ThenByDescending.

Performance Code fix Samples/LC005_MultipleOrderBy/
LC014 Warning

Avoid String.ToLower() or ToUpper() in LINQ queries

Flags ToLower() and ToUpper() on entity properties in EF Core queries, which can stop the database using an index. Use a collation instead.

Performance Manual only Samples/LC014_AvoidStringCaseConversion/
LC015 Warning

Deterministic Pagination: OrderBy required before Skip/Take

Flags Skip, Take, Last, ElementAt and Chunk on unordered EF Core queries, where the database may return rows in a different order each run.

Reliability Code fix Samples/LC015_MissingOrderBy/
LC016 Warning

Avoid DateTime.Now/UtcNow in LINQ queries

Flags DateTime.Now, UtcNow and DateTimeOffset.Now inside EF Core LINQ queries. Hoist the value into a local for cacheable, testable queries.

Performance Code fix Samples/LC016_AvoidDateTimeNow/
LC020 Warning

Avoid untranslatable string comparison overloads

Flags Contains, StartsWith and EndsWith with a StringComparison argument in EF Core queries, which providers often cannot translate to SQL.

Performance Code fix Samples/LC020_StringContainsWithComparison/
LC024 Warning

GroupBy with Non-Translatable Projection

Flags EF Core GroupBy queries that project values SQL cannot translate, which causes runtime errors or accidental client-side grouping.

Performance Manual only Samples/LC024_GroupByNonTranslatable/
LC050 Warning

OrderBy before Distinct is discarded

Flags EF Core queries that sort before Distinct(), where SQL DISTINCT silently drops the ORDER BY, and moves the sort after Distinct().

Correctness Code fix Samples/LC050_OrderByBeforeDistinct/
LC061 Warning

Compiled query is not cached

Flags EF Core EF.CompileQuery and EF.CompileAsyncQuery calls that compile the query on every call instead of once in a static readonly field.

Performance Code fix Samples/LC061_UncachedCompiledQuery/

Raw SQL & Security

Flag SQL construction patterns that can bypass parameterization, tenant filters, or review expectations.

Schema & Modeling

Guard model shape choices that produce fragile entity mappings and unclear relationships.

LC011 Warning

Design: Entity missing Primary Key

Detects EF Core entity types exposed through a DbSet that have no primary key from convention, a [Key] attribute or fluent configuration.

Design Code fix Samples/LC011_EntityMissingPrimaryKey/
LC027 Info

Missing Explicit Foreign Key Property

Flags EF Core reference navigations whose dependent entity has no matching foreign key property, leaving EF Core to create a shadow key.

Design Code fix Samples/LC027_MissingExplicitForeignKey/
LC052 Warning

Model data uses a value that changes on every run

Flags HasData and HasDefaultValue with DateTime.Now or Guid.NewGuid(), which change the EF Core model every run and make EF Core 9 Migrate() throw.

Reliability Manual only Samples/LC052_NonDeterministicModelData/
LC053 Warning

Global query filter silently replaced by another HasQueryFilter

Flags a second unnamed EF Core HasQueryFilter on one entity, which replaces the first and silently drops a tenant or soft-delete filter.

Security Code fix Samples/LC053_OverwrittenQueryFilter/
LC054 Warning

Migrate called inside a user transaction

Flags EF Core Database.Migrate() and MigrateAsync() calls inside a transaction begun on the same context, which EF Core 9 and later reject at startup.

Reliability Code fix Samples/LC054_MigrateInsideTransaction/
LC055 Warning

OnModelCreating override skips the base configuration

Flags EF Core OnModelCreating overrides that never call base.OnModelCreating when the base context, such as IdentityDbContext, configures the model.

Correctness Code fix Samples/LC055_MissingBaseOnModelCreating/