.Select<T>(fields)
Projects only the specified fields into a new instance of T. Supports direct properties, whole navigation objects/collections, and nested navigation paths — including paths that traverse collection properties.
Signature
public static IQueryable<T> Select<T>(this IQueryable<T> query, List<string> fields)
where T : class, new()| Parameter | Type | Description |
|---|---|---|
query | IQueryable<T> | Source query to project |
fields | List<string> | Property paths to include |
Projection rules
| Path style | Behaviour | Example input | Effect on result |
|---|---|---|---|
| Direct scalar | Bound directly | "Name" | Name: "Laptop" |
| Whole navigation object (non-dotted) | Bound as-is | "Category" | Category: { Id: 5, Name: "Electronics", … } |
| Whole navigation collection (non-dotted) | Bound as-is | "Brands" | Brands: [{ Id: 1, … }, …] |
| Dotted through reference navigation | Recursively projected | "Category.Name" | Category: { Id: …, Name: "Electronics" } |
| Dotted through collection navigation | Per-element Select().ToList() | "Category.Vendors.Id" | Category: { Vendors: [{ Id: 1 }, …] } |
| Multi-level (reference + collection) | Nested recursively | "Category.Vendors.Product.Name" | Category: { Vendors: [{ Product: { Name: "…" } }] } |
Id property is always automatically included alongside any requested sub-fields.Validations
queryandfieldscannot be null.fieldsmust have at least one entry.- Every field must exist on
T(case-insensitive, auto-normalized). Tmust have a parameterless constructor.
.Select<T>(fields) requires T to have a parameterless (default) constructor. If T does not have one, a LogicException is thrown. Most EF Core entity classes have parameterless constructors by default. If your type does not, use .SelectDynamic<T> instead.Returns
IQueryable<T> — a projected query. New instances of T are constructed via the parameterless constructor and member-bound from the requested fields.
Examples
Direct scalars.
var projected = dbContext.Products
.Select(new List<string> { "Id", "Name", "Price" });Dotted path through a reference navigation.
var projected = dbContext.Products
.Select(new List<string> { "Id", "Name", "Category.Name" });Category is projected with only the requested Name sub-field (Id auto-included).
Dotted path through a collection navigation.
var projected = dbContext.Products
.Select(new List<string> { "Id", "Name", "Category.Vendors.Id" });Category.Vendors is a collection — each Vendor element is projected with only its Id (Id auto-included).
Whole navigation object (non-dotted).
var projected = dbContext.Products
.Select(new List<string> { "Id", "Name", "Category" });The entire Category object is bound as-is.
Whole collection (non-dotted).
var projected = dbContext.Products
.Select(new List<string> { "Id", "Name", "Brands" });The entire Brands collection is bound as-is.
JSON-driven projection.
{ "fields": ["Id", "Name", "Category.Name"] }See also
.SelectDynamic<T>— non-generic dynamic variant (no parameterless constructor needed)..Filter<T>— applywhere → order → page → selectin one call.- JSON Cookbook: Select.