Introduction

If you are learning C#, LINQ, or Entity Framework Core, you will often see two interfaces:

Both are used with LINQ, but they work differently.

The main difference is where the query runs.

What is IEnumerable in C#?

IEnumerable<T> is mainly used when the data is already available in memory.

For example :

Code
List<int> numbers = new()
{
    10, 20, 30, 40, 50
};

IEnumerable<int> result = numbers
    .Where(x => x > 20);

Here, the numbers are already in memory, so the Where() condition runs inside the application.

Simple flow :

Code
Data → Memory → LINQ → Result

IEnumerable is commonly used with:

You can see in this diagram :

What is IQueryable in C#?

IQueryable<T> is mainly used for querying external data sources, especially databases.

For example, with Entity Framework Core:

Code
IQueryable<Product> products = dbContext.Products;

var result = await products
    .Where(x => x.Price > 1000)
    .ToListAsync();

Entity Framework Core can convert this LINQ query into SQL.

It may generate SQL similar to:

Code
SELECT * FROM Products WHERE Price > 1000;

The filtering happens in the database instead of loading all products into memory.

Simple flow :

Code
LINQ Query → SQL → Database → Result

You can see in this diagram :

IEnumerable vs IQueryable

Feature

IEnumerable

IQueryable

Works mainly with

In-memory data

Database data

Query runs

In application

Usually at database

SQL translation

No

Yes, through provider

Best for

Small/in-memory collections

Database queries

Common with

List, Array

Entity Framework Core

A Database Example

Suppose we have a Products table containing 1 million records.

We want products where:

Code
Price > 1000


Using IQueryable

With Entity Framework Core:

Code
IQueryable<Product> products = dbContext.Products;

var result = await products
    .Where(x => x.Price > 1000)
    .ToListAsync()

Conceptually, the process is:

Code
Application
    ↓
LINQ Where(x => x.Price > 1000)
    ↓
Entity Framework Core
    ↓
SQL
    ↓
Database
    ↓
Only matching records
    ↓
Application

The filtering is performed by the database.

What Happens When You Switch to IEnumerable?

Code
IQueryable<Product> products = dbContext.Products;

IEnumerable<Product> result = products
    .AsEnumerable()
    .Where(x => x.Price > 1000);

AsEnumerable() changes the LINQ operations that follow it to LINQ-to-Objects.

So the Where() after AsEnumerable() is evaluated in the application.

Conceptually:

Code
Database
    ↓
Records are read
    ↓
Application memory
    ↓
Where(x => x.Price > 1000)
    ↓
Filtered result

This can be slow if the database has a lot of records.

If the database contains a large number of records, this can result in unnecessary data transfer and increased memory usage.

Conclusion

IEnumerable<T> is mainly used for working with data in application memory, while IQueryable<T> is used to build queries that can be executed by external data sources such as databases. Understanding where the query is executed helps you write more efficient and performant LINQ and Entity Framework Core code.

Hope this helps you!