DynamicWhere.ex
DynamicWhere.exv2.1.0·docs

.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()
ParameterTypeDescription
queryIQueryable<T>Source query to project
fieldsList<string>Property paths to include

Projection rules

Path styleBehaviourExample inputEffect on result
Direct scalarBound 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 navigationRecursively projected"Category.Name"Category: { Id: …, Name: "Electronics" }
Dotted through collection navigationPer-element Select().ToList()"Category.Vendors.Id"Category: { Vendors: [{ Id: 1 }, …] }
Multi-level (reference + collection)Nested recursively"Category.Vendors.Product.Name"Category: { Vendors: [{ Product: { Name: "…" } }] }
Note
For nested entities (reference or collection), the Id property is always automatically included alongside any requested sub-fields.

Validations

  • query and fields cannot be null.
  • fields must have at least one entry.
  • Every field must exist on T (case-insensitive, auto-normalized).
  • T must have a parameterless constructor.
Warning
Parameterless constructor required. .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