C#  

Difference Between IEnumerable and IQueryable in C#

Understanding the difference between IEnumerable and IQueryable is crucial for writing efficient and optimized data access code in C#. Both are used for querying data, but they differ significantly in how and where the query is executed.

This concept is especially important when working with Entity Framework Core, LINQ, and large datasets.

What is IEnumerable

IEnumerable is an interface used for in-memory data collection iteration.

Key characteristics:

  • Works with in-memory collections

  • Executes query immediately after enumeration

  • Filtering happens in application memory

  • Suitable for small datasets

Example

var data = context.Users.ToList(); // Data loaded into memory
var result = data.Where(x => x.Name.StartsWith("A"));

In this case, all records are first fetched from the database, and filtering happens in memory.

What is IQueryable

IQueryable is an interface designed for querying remote data sources such as databases.

Key characteristics:

  • Works with remote data sources (like SQL Server)

  • Uses deferred execution

  • Query is translated into SQL and executed in the database

  • More efficient for large datasets

Example

var result = context.Users
    .Where(x => x.Name.StartsWith("A"));

Here, the filtering is converted into a SQL query and executed in the database.

Key Differences Between IEnumerable and IQueryable

FeatureIEnumerableIQueryable
Execution LocationIn-memoryDatabase / Remote
Query ExecutionImmediateDeferred
PerformanceSlower for large dataFaster for large data
FilteringClient-sideServer-side
Use CaseSmall datasetsLarge datasets

Execution Behavior Explained

IEnumerable Execution Flow

  1. Fetch all data from database

  2. Store data in memory

  3. Apply filters using LINQ

IQueryable Execution Flow

  1. Build query expression

  2. Convert to SQL

  3. Execute in database

  4. Return filtered result

Performance Comparison Example

Using IEnumerable (Inefficient)

var users = context.Users.ToList();
var filtered = users.Where(u => u.Age > 25);
  • Loads all users into memory

  • Then filters → high memory usage

Using IQueryable (Optimized)

var filtered = context.Users
    .Where(u => u.Age > 25)
    .ToList();
  • Generates SQL query

  • Only required data is fetched

When to Use IEnumerable

  • Working with small datasets

  • Data already loaded into memory

  • Performing operations not supported by database

When to Use IQueryable

  • Working with databases

  • Handling large datasets

  • Applying filters, sorting, pagination at database level

Common Mistakes to Avoid

  • Calling ToList() too early (forces immediate execution)

  • Mixing IEnumerable and IQueryable unintentionally

  • Performing heavy filtering after loading data into memory

Real-World Scenario

In a production application:

  • Use IQueryable for APIs and database queries

  • Use IEnumerable for in-memory transformations

Example:

var users = context.Users
    .Where(u => u.IsActive)
    .OrderBy(u => u.Name)
    .ToList();

This ensures optimized SQL execution.

Conclusion

IEnumerable and IQueryable may look similar, but their behavior is fundamentally different. Choosing the right one directly impacts performance, scalability, and efficiency of your application. Always prefer IQueryable when working with databases to ensure that filtering and execution happen at the data source level.