Entity Framework
Multiple Columns
C# Programming
Database Query
LINQ

Select multiple columns using Entity Framework

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Entity Framework, “selecting multiple columns” usually means projecting only the fields you need instead of loading the entire entity. The right tool is LINQ Select, which tells EF to generate SQL for a narrower result shape. That is both cleaner and more efficient than fetching whole rows when you only need a few values.

Use Projection With Select

Suppose you have a Product entity but a page only needs the product name and price. Instead of querying full Product objects, project just those columns:

csharp
1using var db = new AppDbContext();
2
3var items = await db.Products
4    .Select(p => new
5    {
6        p.ProductId,
7        p.ProductName,
8        p.Price
9    })
10    .ToListAsync();

EF translates that into SQL that selects only the requested columns. That matters because the database sends less data, and EF does less tracking and materialization work.

Anonymous types are great for short-lived query results used inside the same method.

Prefer DTOs for Reusable Shapes

If the selected columns represent a real response model, project into a DTO instead of an anonymous type:

csharp
1public class ProductListItem
2{
3    public int Id { get; set; }
4    public string Name { get; set; } = "";
5    public decimal Price { get; set; }
6}
7
8using var db = new AppDbContext();
9
10var items = await db.Products
11    .Where(p => p.IsActive)
12    .Select(p => new ProductListItem
13    {
14        Id = p.ProductId,
15        Name = p.ProductName,
16        Price = p.Price
17    })
18    .ToListAsync();

This is the most common pattern in APIs and MVC views because the result type is explicit and reusable.

Query Syntax and Method Syntax Both Work

Some teams prefer query syntax for readability:

csharp
1var items =
2    await (from p in db.Products
3           where p.IsActive
4           select new
5           {
6               p.ProductId,
7               p.ProductName,
8               p.Price
9           })
10    .ToListAsync();

Under the hood, this is still LINQ projection. Use the style your codebase prefers, but keep the projection close to the query so it is obvious which columns are actually being requested.

You can also project columns from navigation properties without loading full related entities. For example:

csharp
1var orders = await db.Orders
2    .Select(o => new
3    {
4        o.OrderId,
5        CustomerName = o.Customer.Name,
6        o.CreatedAt
7    })
8    .ToListAsync();

EF will generate the necessary join in SQL. This is often better than using Include when you only need a few fields from the related table.

The rule of thumb is:

  • use Include when you want full related entities
  • use Select when you want a shaped result with only specific fields

Why Projection Is Better Than Loading Full Entities

A common beginner pattern is:

csharp
var products = await db.Products.ToListAsync();
var result = products.Select(p => new { p.ProductId, p.ProductName, p.Price });

That works, but it loads every mapped column first and only trims the data afterward in memory. The projection should happen before ToListAsync so the database query itself is selective.

Correct:

csharp
var result = await db.Products
    .Select(p => new { p.ProductId, p.ProductName, p.Price })
    .ToListAsync();

That difference can matter a lot on large tables.

Tracking and Read-Only Queries

If the result is read-only, combine projection with AsNoTracking:

csharp
1var items = await db.Products
2    .AsNoTracking()
3    .Select(p => new ProductListItem
4    {
5        Id = p.ProductId,
6        Name = p.ProductName,
7        Price = p.Price
8    })
9    .ToListAsync();

Since you are not returning entities for later updates, change tracking usually adds overhead without benefit.

Common Pitfalls

The biggest pitfall is projecting after materialization instead of before it. Once ToList or ToListAsync runs, the database work is already done.

Another common mistake is using Include when only a few related columns are needed. That tends to pull back more data than necessary and can complicate query shape.

Be careful with custom methods inside Select. EF can translate many simple expressions, but arbitrary .NET methods may fail translation and force client-side evaluation or throw an exception.

Also remember that anonymous types are local to the method. If you need to return the data from a service or controller, use a named DTO instead.

Summary

  • Use LINQ Select to project only the columns you need.
  • Project before ToListAsync, not after.
  • Anonymous types are fine for local query results; DTOs are better for reusable shapes.
  • Use projection from navigation properties when you need a few related fields.
  • Combine projection with AsNoTracking for efficient read-only queries.

Course illustration
Course illustration

All Rights Reserved.