Projections : Entity Framework Core
Overview
Projections in Entity Framework Core are a way to select specific parts of your entity model rather than returning the full entity. This is useful for performance and separation of concerns — especially when you only need a subset of data (e.g. for a view model, DTO, or UI list).
What Are Projections in EF Core?
A projection transforms your query results into another shape using .Select()
.
You can:
- Project into anonymous types
- Project into DTOs / ViewModels
- Use partial columns to reduce the size of your result set
It’s equivalent to writing a SELECT Name, Price FROM Products
in SQL rather than SELECT *
.
Advantages of Using Projections
- Performance: Only retrieves the data you need (fewer columns, less memory).
- Security: Avoid exposing unnecessary data (like passwords or foreign keys).
- Clear intent: Makes the purpose of the query obvious.
- Better for frontend APIs: Map data to shape expected by consumer.
Drawbacks
- You lose change tracking if you project into anything other than an entity.
- You can’t easily update the database from the projected object.
- Some complex projections (especially involving navigation properties) can be tricky.
Example: Projection with Anonymous Type
Suppose you have the following model:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public Category Category { get; set; }
}
Projecting to an anonymous type
var products = await _context.Products
.Select(p => new
{
p.Name,
p.Price,
CategoryName = p.Category.Name
})
.ToListAsync();
This returns a list of anonymous objects like:
{ Name = "Apples", Price = 1.20m, CategoryName = "Fruit" }
Projecting to a DTO
public class ProductDto
{
public string Name { get; set; }
public string CategoryName { get; set; }
}
var products = await _context.Products
.Select(p => new ProductDto
{
Name = p.Name,
CategoryName = p.Category.Name
})
.ToListAsync();
Notes on Anonymous Type Usage
- Great for read-only scenarios (like sending data to UI).
- You can't return them from a method unless it's
dynamic
or part of the same LINQ query scope. - You can use them inside Razor views or inside controller methods if you don’t need to strongly type the result.
Pro Tips
- Always project before calling
.ToListAsync()
to make sure only the needed fields are pulled from the DB. - You can project nested navigation properties — but EF Core must be able to translate the query to SQL.
- For large results or API endpoints, consider using
AsNoTracking()
to disable change tracking for better performance.
Summary
Concept | Description |
---|---|
Projection | Selecting a subset of fields or mapping entities to a new shape |
Anonymous Type | Used in .Select() when you don’t need a named class |
When to Use | UI lists, DTOs, or when minimizing data transfer |
Key Syntax | .Select(x => new { x.Foo, x.Bar }) |