DynamicWhere.ex
DynamicWhere.exv2.1.0·docs

.SelectDynamic<T>(fields)

Projects only the specified fields using System.Linq.Dynamic.Core's string-based Select, returning a non-generic dynamic IQueryable. Dotted navigation paths are projected as nested dynamic objects that mirror the navigation hierarchy, including through collection properties.

Signature

public static IQueryable SelectDynamic<T>(this IQueryable<T> query, List<string> fields)
    where T : class
ParameterTypeDescription
queryIQueryable<T>Source query to project
fieldsList<string>Property paths to include

Projection rules

Path styleBehaviourExample inputDynamic result
Non-dotted scalarProjected as-is"Name"Name: "Laptop"
Non-dotted objectProjected as-is (whole object)"Category"Category: { Id: 5, Name: "Electronics" }
Non-dotted collectionProjected as-is (whole collection)"Brands"Brands: [{ Id: 1, … }]
Dotted through reference navigationNested object per segment"Category.Name"Category: { Name: "Electronics" }
Dotted through collection navigationSelect lambda per collection segment"Category.Vendors.Id"Category: { Vendors: [{ Id: 1 }] }
Multi-level dotted (reference + collection)Mixed nesting and Select lambdas"Category.Vendors.Product.Name"Category: { Vendors: [{ Product: { Name: "…" } }] }
Nested collections (any depth)Select lambda at each collection level"A.ListB.ListC.Name"A: { ListB: [{ ListC: [{ Name: "…" }] }] }
Multi-level dotted (deep reference)Deeply nested objects"Category.SubCategory.Name"Category: { SubCategory: { Name: "Laptops" } }

Merging rule

Multiple dotted fields sharing the same root segment are merged into the same nested object:

["Category.Name", "Category.Id"]

produces Category: { Name: "...", Id: 5 }.

Whole-vs-sub-field precedence

Warning
When both a whole-navigation field (e.g., "Category") and sub-field paths sharing the same root segment (e.g., "Category.Name") are requested, the sub-field projection takes precedence and the whole-navigation entry is silently dropped.

Validations

  • query and fields cannot be null.
  • fields must have at least one entry.
  • Every field must exist on T (case-insensitive, auto-normalized).
Note
Unlike .Select<T>, this method does not require a parameterless constructor on T.

Returns

IQueryable — a dynamic projected query where each element is an anonymous object.

Examples

Direct scalars.

var dynQuery = dbContext.Products
    .SelectDynamic(new List<string> { "Id", "Name", "Price" });
{ "Id": 7, "Name": "Laptop Pro", "Price": 1299.99 }

Dotted path through reference navigation (nested object).

var dynQuery = dbContext.Products
    .SelectDynamic(new List<string> { "Id", "Name", "Price", "Category.Name" });
{ "Id": 7, "Name": "Laptop Pro", "Price": 1299.99, "Category": { "Name": "Electronics" } }

Dotted path through collection navigation (Select lambda).

var dynQuery = dbContext.Products
    .SelectDynamic(new List<string> { "Id", "Name", "Category.Vendors.Id" });
{ "Id": 7, "Name": "Laptop Pro", "Category": { "Vendors": [{ "Id": 3 }, { "Id": 7 }] } }

Multi-level dotted (reference → collection → reference).

var dynQuery = dbContext.Products
    .SelectDynamic(new List<string> { "Id", "Category.Vendors.Product.Name" });
{ "Id": 7, "Category": { "Vendors": [{ "Product": { "Name": "Laptop Pro" } }] } }

Merged sub-fields.

var dynQuery = dbContext.Products
    .SelectDynamic(new List<string> { "Id", "Category.Name", "Category.Id" });
{ "Id": 7, "Category": { "Name": "Electronics", "Id": 5 } }

Whole navigation object.

var dynQuery = dbContext.Products
    .SelectDynamic(new List<string> { "Id", "Name", "Category" });
{ "Id": 7, "Name": "Laptop Pro", "Category": { "Id": 5, "Name": "Electronics" } }

Whole collection.

var dynQuery = dbContext.Products
    .SelectDynamic(new List<string> { "Id", "Name", "OrderItems" });
{ "Id": 7, "Name": "Laptop Pro", "OrderItems": [ { "Id": 1, "Quantity": 2 } ] }

Deep reference nesting.

var dynQuery = dbContext.Products
    .SelectDynamic(new List<string> { "Id", "Category.SubCategory.Name" });
{ "Id": 7, "Category": { "SubCategory": { "Name": "Laptops" } } }

See also