DynamicWhere.ex
DynamicWhere.exv3.4.0·docs

Extension Methods

Every extension method lives in DynamicWhere.ex.Source.Extension and operates on IQueryable<T> — with IEnumerable<T> overloads for in-memory variants. The methods fall into four intents: projection, filtering, composition, and materialization.

Projection

Project a query into a typed shape or a dynamic shape. Both support direct properties, whole navigation objects, whole collections, and dotted paths through reference and collection navigations.

MethodSignatureReturnsAsyncLink
Select.Select<T>(List<string> fields)IQueryable<T>NoDocs
SelectDynamic.SelectDynamic<T>(List<string> fields)IQueryableNoDocs

Filtering

Build the where-clause, group, order, or paginate the query — one building block at a time.

MethodSignatureReturnsAsyncLink
Where.Where<T>(Condition condition)IQueryable<T>NoDocs
Where.Where<T>(ConditionGroup group)IQueryable<T>NoDocs
Group.Group<T>(GroupBy groupBy)IQueryableNoDocs
Order.Order<T>(OrderBy) / .Order<T>(List<OrderBy>)IQueryable<T>NoDocs
Page.Page<T>(PageBy page)IQueryable<T>NoDocs

Composition

Apply a complete Filter or Summary composition to the query. Each returns an IQueryable so you can chain further operations before materializing.

MethodSignatureReturnsAsyncLink
Filter.Filter<T>(Filter filter)IQueryable<T>NoDocs
FilterDynamic.FilterDynamic<T>(Filter filter)IQueryableNoDocs
Summary.Summary<T>(Summary summary)IQueryableNoDocs

Materialization

Execute the composed query and return a paginated result — typed, dynamic, summary, or segment. The async terminals count with EF Core's CountAsync and read with EF Core's ToListAsync. Since 3.2.0 that includes the dynamic Filter's read and the Summary's count and read: the count used to run synchronously, and the reads through Dynamic LINQ, with no token to pass on. ToListAsync(Summary) on a provider that is not EF Core's keeps its synchronous count and Dynamic LINQ's read, and ToListAsync(Segment) combines its sets into one query and then counts and reads it exactly as a Filter does.

MethodSignatureReturnsAsyncLink
ToList (Filter).ToList<T>(Filter, bool getQueryString = false)FilterResult<T>NoDocs
ToListAsync (Filter).ToListAsync<T>(Filter, bool getQueryString = false)Task<FilterResult<T>>YesDocs
ToListAsync (Filter, token).ToListAsync<T>(Filter, CancellationToken) / .ToListAsync<T>(Filter, bool getQueryString, CancellationToken)Task<FilterResult<T>>YesDocs
ToListDynamic (Filter).ToListDynamic<T>(Filter, bool getQueryString = false)FilterResult<dynamic>NoDocs
ToListAsyncDynamic (Filter).ToListAsyncDynamic<T>(Filter, bool getQueryString = false)Task<FilterResult<dynamic>>YesDocs
ToListAsyncDynamic (Filter, token).ToListAsyncDynamic<T>(Filter, CancellationToken) / .ToListAsyncDynamic<T>(Filter, bool getQueryString, CancellationToken)Task<FilterResult<dynamic>>YesDocs
ToList (Summary).ToList<T>(Summary, bool getQueryString = false)SummaryResultNoDocs
ToListAsync (Summary).ToListAsync<T>(Summary, bool getQueryString = false)Task<SummaryResult>YesDocs
ToListAsync (Summary, token).ToListAsync<T>(Summary, CancellationToken) / .ToListAsync<T>(Summary, bool getQueryString, CancellationToken)Task<SummaryResult>YesDocs
ToListAsync (Segment).ToListAsync<T>(Segment segment)Task<SegmentResult<T>>Yes (only)Docs
ToListAsync (Segment, token).ToListAsync<T>(Segment, CancellationToken)Task<SegmentResult<T>>Yes (only)Docs
A CancellationToken on every async terminal (3.2.0)
ToListAsync and ToListAsyncDynamic with a Filter, ToListAsync with a Summary and ToListAsync with a Segment each have overloads that take a CancellationToken. The token reaches the count and the read. The overloads sit beside the 3.1 signatures, which are unchanged, so code compiled against 3.1 still binds. ToListAsync(filter, default) no longer compiles, because default fits both getQueryString and the token; neither do ToListAsyncDynamic(filter, default) and ToListAsync(summary, default). Write false, a token, or a named argument. And a reflection lookup of ToListAsyncDynamic by name alone now finds three methods where it found one: pass the parameter types to Type.GetMethod.
Warning
Segment operations are async-only. There is no synchronous ToList<T>(Segment) variant. The set operations (Union / Intersect / Except) combine every ConditionSet into one query, which the database orders and pages.

In-memory overloads

Exactly three of the terminals also expose an IEnumerable<T> overload — ToList(Filter), ToListDynamic(Filter) and ToList(Summary). These wrap the collection with AsQueryable() and delegate to the typed overload — handy for unit tests and in-process pipelines. Nothing else has one: there is no ToListDynamic(Summary), and no async or composable method works on an IEnumerable<T> source. Counting those three and the seven overloads that take a CancellationToken, the library ships 28 extension methods.

Note
Pass getQueryString: true to any Filter or Summary materialization call to capture the generated SQL on the result. .ToListAsync<T>(Segment) takes no such parameter, so SegmentResult<T>.QueryString is always null. The call reaches EF Core's .ToQueryString(), so on a non-EF Core source the property holds a placeholder sentence rather than SQL.
Note
Every one of the 28 begins by asking the policy layer whether this type may be queried at all. A type marked [DwEntity(RequirePolicy = true)] throws PolicyException with PolicyRequired when it is reached through any of them without ApplyPolicy. Plain LINQ on the same DbSet is not intercepted — the guard covers this library's methods, not Entity Framework Core's.

Next steps

  • Filter — the JSON shape that drives the typed pipeline.
  • Summary — the aggregate-reporting pipeline.
  • Segment — set operations across multiple condition sets.