DynamicWhere.ex
DynamicWhere.exv3.4.0·docs

.Where<T>(...)

Apply a single Condition or a full ConditionGroup (with optional nested sub-groups joined by And / Or) to a query.

Single condition overload

public static IQueryable<T> Where<T>(this IQueryable<T> query, Condition condition)
    where T : class
ParameterTypeDescription
conditionConditionThe filter condition

Returns: IQueryable<T> — filtered query.

Condition-group overload

public static IQueryable<T> Where<T>(this IQueryable<T> query, ConditionGroup group)
    where T : class
ParameterTypeDescription
groupConditionGroupThe filter group — flat Conditions plus optional nested SubConditionGroups

Returns: IQueryable<T> — filtered query.

Validations

Condition validation (applied per condition):

  • Field must be non-empty and exist on T (case-insensitive, auto-normalized) — error code InvalidField.
  • Field's first segment must not be one of the expression parser's own words — new, iif, np, isnull, is, as, cast, true, false, null, in any letter case — FieldPath[{path}]StartsWithReservedName. The same check covers Orders, Selects, GroupBy.Fields and AggregateBy.Field; only the first segment counts, so Owner.New names the member.
  • Between / NotBetween require exactly 2 values — RequiredTwoValue.
  • In / IIn / NotIn / INotIn require 1+ values — RequiredValues.
  • IsNull / IsNotNull require 0 values — NotRequiredValues.
  • All other operators require exactly 1 value — RequiredOneValue({Operator}).
  • Guid values must parse as Guid — InvalidFormat.
  • Number values must be a literal the expression parser reads — invariant, no thousands separator, no leading plus, no NaN — and one it can compare with the member the condition names, so 1.5 is refused on an int? and 1e-7 on a decimal (3.3.0) — InvalidFormat. The server's culture decides nothing. See Condition validation.
  • Boolean values must parse as bool — InvalidFormat.
  • Date / DateTime values must be ISO 8601, year-first, or a format declared with DwDates.Configure — AmbiguousDateFormat for a day/month-first date such as 01/09/2026, InvalidFormat otherwise. The server's culture decides nothing. See Condition validation.
  • The DataType / Operator pair must be one the library supports — checked last, when the predicate is built, and reported as Unsupported combination of DataType '<DataType>' and Operator '<Operator>'.

ConditionGroup validation (applied per group):

  • All Condition.Sort values within the group must be unique — ConditionsUniqueSort.
  • All SubConditionGroups.Sort values must be unique — SubConditionsGroupsUniqueSort.
  • Each child condition is validated individually.
Note
When a condition's Field path traverses a collection property (e.g., Orders.OrderItems.ProductName), the library automatically wraps the inner segment in a .Any() lambda. There is no built-in .All() support.

Example — single condition

var condition = new Condition
{
    Sort = 1,
    Field = "Name",
    DataType = DataType.Text,
    Operator = Operator.IContains,
    Values = new List<object> { "phone" }
};

var query = dbContext.Products.Where(condition);
{
  "sort": 1,
  "field": "Name",
  "dataType": "Text",
  "operator": "IContains",
  "values": ["phone"]
}

Example — condition group with nested OR

var group = new ConditionGroup
{
    Connector = Connector.And,
    Conditions = new List<Condition>
    {
        new Condition
        {
            Sort = 1,
            Field = "IsActive",
            DataType = DataType.Boolean,
            Operator = Operator.Equal,
            Values = new List<object> { true }
        }
    },
    SubConditionGroups = new List<ConditionGroup>
    {
        new ConditionGroup
        {
            Sort = 1,
            Connector = Connector.Or,
            Conditions = new List<Condition>
            {
                new Condition { Sort = 1, Field = "Role", DataType = DataType.Text, Operator = Operator.Equal, Values = new List<object> { "Admin" } },
                new Condition { Sort = 2, Field = "Role", DataType = DataType.Text, Operator = Operator.Equal, Values = new List<object> { "Manager" } }
            }
        }
    }
};

var query = dbContext.Users.Where(group);
{
  "connector": "And",
  "conditions": [
    { "sort": 1, "field": "IsActive", "dataType": "Boolean", "operator": "Equal", "values": ["true"] }
  ],
  "subConditionGroups": [
    {
      "sort": 1,
      "connector": "Or",
      "conditions": [
        { "sort": 1, "field": "Role", "dataType": "Text", "operator": "Equal", "values": ["Admin"] },
        { "sort": 2, "field": "Role", "dataType": "Text", "operator": "Equal", "values": ["Manager"] }
      ],
      "subConditionGroups": []
    }
  ]
}

Equivalent SQL: WHERE IsActive = true AND (Role = 'Admin' OR Role = 'Manager').

See also