Segment
A Segment stitches together multiple ConditionSet objects with Union / Intersect / Except set operations, then applies optional sort and pagination. A projection, if you give one, is applied after they are combined, to the ordered and paged rows.
Properties
| Property | Type | Description |
|---|---|---|
ConditionSets | List<ConditionSet> | Ordered condition sets. |
Selects | List<string>? | Optional field projection, applied last to the combined, ordered and paged rows, as for a Filter. |
Orders | List<OrderBy>? | Optional sort criteria. |
Page | PageBy? | Optional pagination. |
Union and Intersect join the sets' conditions, and Except removes its set's rows by primary key. A type with no primary key uses SQL UNION / INTERSECT / EXCEPT. Segments are executed exclusively through ToListAsync<T>(Segment). There is no synchronous counterpart.C# example
var segment = new Segment
{
ConditionSets = new List<ConditionSet>
{
new ConditionSet
{
Sort = 0,
ConditionGroup = new ConditionGroup
{
Connector = Connector.And,
Conditions = new List<Condition>
{
new Condition
{
Sort = 1, Field = "Country",
DataType = DataType.Text, Operator = Operator.Equal,
Values = new List<object> { "IQ" }
}
}
}
},
new ConditionSet
{
Sort = 1,
Intersection = Intersection.Except,
ConditionGroup = new ConditionGroup
{
Connector = Connector.And,
Conditions = new List<Condition>
{
new Condition
{
Sort = 1, Field = "IsBlocked",
DataType = DataType.Boolean, Operator = Operator.Equal,
Values = new List<object> { true }
}
}
}
}
},
Orders = new List<OrderBy>
{
new OrderBy { Sort = 1, Field = "Name" }
},
Page = new PageBy { PageNumber = 1, PageSize = 50 }
};
SegmentResult<Customer> result = await dbContext.Customers.ToListAsync(segment);JSON example
{
"conditionSets": [
{
"sort": 0,
"intersection": null,
"conditionGroup": {
"connector": "And",
"conditions": [
{ "sort": 1, "field": "Country", "dataType": "Text", "operator": "Equal", "values": ["IQ"] }
],
"subConditionGroups": []
}
},
{
"sort": 1,
"intersection": "Except",
"conditionGroup": {
"connector": "And",
"conditions": [
{ "sort": 1, "field": "IsBlocked", "dataType": "Boolean", "operator": "Equal", "values": [true] }
],
"subConditionGroups": []
}
}
],
"orders": [
{ "sort": 1, "field": "Name", "direction": "Ascending" }
],
"page": { "pageNumber": 1, "pageSize": 50 }
}Clone
Segment.Clone() is public since 3.3.0. It returns a deep copy — every condition set with its own condition group, the Selects list, each order and the page — so nothing either request is given afterwards reaches the other.
Every node is new. The values a condition carries stay the caller's own objects, in a new list: they are scalars decoded from JSON and nothing in the pipeline writes to them.
Segment page2 = caller.Clone();
page2.Page!.PageNumber = 2; // the caller's own segment is untouchedReading one request again with a part changed, the next page or another order, used to mean rebuilding it around the caller's own clauses, which leaves both requests holding one condition tree: a rewrite of either reaches both. The library has cloned before rewriting anything since 3.0; callers could not until now. A branch the caller left null stays null, and a null entry inside a list is copied as a null entry rather than failing on it (3.3.0), so the refusal belongs to the method that runs the request and reads the same for a copy.