S9022 — Redundant "Include" calls should be removed

Language
C#
Type
Code smell
Severity
Minor
Tags
entity-framework-core, entity-framework, orm, database

An Include or ThenInclude call can be entirely inert: Entity Framework Core generates the exact same SQL with or without it.

Why is this an issue?

Entity Framework Core resolves the navigation path of every Include/ThenInclude call and merges calls that resolve to the same path into a single join. Repeating Include for a navigation that is already included, without adding a new ThenInclude afterwards, generates identical SQL to removing the repeated call — it adds nothing but noise and can mislead a reader into thinking it changes what is loaded.

Exceptions

The rule does not apply when:

How to fix it

Remove the Include (or ThenInclude) call that has no effect.

Code examples

Noncompliant code example


var students = await context.Students
    .Include(s => s.Enrollments) // Noncompliant: "Enrollments" is already included below
    .Include(s => s.Enrollments)
    .ToListAsync();

Compliant solution


var students = await context.Students
    .Include(s => s.Enrollments)
    .ToListAsync();

This repeated Include is not redundant — it branches into two different ThenInclude calls:


var students = await context.Students
    .Include(s => s.Enrollments).ThenInclude(e => e.Course)
    .Include(s => s.Enrollments).ThenInclude(e => e.Student) // Compliant: re-anchors before a different ThenInclude
    .ToListAsync();

Resources

Documentation

Related rules

↑ Back to top