Skip to main content

C# and .NET Business Scenarios

Generated method names are defined by Q.cs, Requests/*Request.cs, and Models/*.cs. Inspect those files before writing application code; do not translate a Java or Python method by hand.

Shared query capability​

.NET implements the complete seven-runtime native query profile: typed scalar and nested relation predicates, typed relation selection through child Requests, projection and ordering, grouping and portable aggregates, relation statistics, facets, ordinary/continuous/ID-set pagination, and exact per-parent Top-N. See the cross-language query contract for the capability catalog and audited source revision.

Start with the common data-operations guide for the distinction between row results, grouped analytics, relation metrics, and Facet sidecars.

Query and stable pagination​

var result = await Q.CustomerOrders()
.Comment("Find matching orders")
.WithOrderNumberContaining("WEB-")
.OrderByIdAscending()
.Offset(0)
.Limit(20)
.Purpose("Prepare the authorized order review page")
.ExecuteForListAsync(context);

The ordinary Request exposes filters, sorting, projections and aggregates. Purpose returns an ExecutableCustomerOrderRequest; only that state exposes execution. There is no (context, service) overload.

Load generated entities and relations​

ExecuteForListAsync(context) returns generated entity instances, not raw provider records. Reverse relations use generated Select... / Select...With methods; read the parent Request source for their exact names and supply a typed child Request for ordering and per-parent limits.

Count, totals, and facets​

The generated Request exposes named portable aggregates. Add GroupBy... for one analytic result row per group:

var groups = await Q.Schools()
.WithNameContaining("School")
.GroupBySchoolType()
.CountAs("schoolCount")
.SumStudentCapacityAs("capacityTotal")
.AvgStudentCapacityAs("capacityAverage")
.MinStudentCapacityAs("capacityMinimum")
.MaxStudentCapacityAs("capacityMaximum")
.Comment("Aggregate schools by type")
.Purpose("Build the capacity dashboard")
.ExecuteForRowsAsync(context);

var firstCount = groups.Rows[0]["schoolCount"].Raw;

ExecuteForRowsAsync preserves group keys and aliases in QueryResult.Rows. Aliases are not writable entity properties. Relation statistics decorate parents without loading all children:

var types = await Q.SchoolTypesWithMinimalFields()
.SelectCode()
.CountSchoolsAs("schoolCount")
.SumStudentCapacityOfSchoolsAs("capacityTotal", Q.Schools())
.Comment("Calculate statistics for every school type")
.Purpose("Render type summary cards")
.ExecuteForListAsync(context);

Include-all and matched-only facets​

var rows = await Q.Schools()
.WithNameContaining("Primary")
.FacetBySchoolTypeAs(
"schoolTypes",
Q.SchoolTypesWithMinimalFields()
.SelectCode()
.SelectName()
.CountSchoolsAs("schoolCount"),
includeAllFacets: true)
.Comment("Search schools and calculate type buckets")
.Purpose("Render the school search page")
.ExecuteForListAsync(context);

var buckets = rows.Facet("schoolTypes");
var firstCount = buckets?[0]["schoolCount"].Raw;

true preserves allowed zero-count buckets; use false for matched-only values. Restrict the allowed bucket domain on the child Request with Q.SchoolTypesWithMinimalFields().WithCodeIn("PRIMARY", "SECONDARY"). Multiple named Facets can be chained:

var rows = await Q.Schools()
.FacetBySchoolTypeAs(
"schoolTypes",
Q.SchoolTypesWithMinimalFields().SelectCode().CountSchoolsAs("count"),
includeAllFacets: true)
.FacetByPlatformAs(
"platforms",
Q.PlatformsWithMinimalFields().SelectName().CountSchoolsAs("count"),
includeAllFacets: false)
.Comment("Calculate school type and platform facets")
.Purpose("Render two authorized filter panels")
.ExecuteForListAsync(context);

The main rows and rows.Facet(name) sidecars are separate. ADO.NET providers translate these requests into database-native COUNT, SUM, AVG, MIN, MAX, and GROUP BY. Never replace a missing generated operator with interpolated SQL.

Create and audited save​

var order = Q.CustomerOrders()
.Comment("Create a validated order")
.Purpose("Persist an authorized checkout")
.NewEntity(context);

order.UpdateOrderNumber("WEB-10001");
order = await order.AuditAs("Create validated checkout order").SaveAsync(context);

order.UpdateOrderNumber("WEB-10001-R1");
order = await order.AuditAs("Approve revised order number").SaveAsync(context);

order.MarkForDeletion();
await order.AuditAs("Cancel duplicate checkout order").SaveAsync(context);

Query the complete current entity before update to preserve the loaded original version and Checker inputs. SaveAsync rejects stale versions and emits the server mutation audit plus the separately attributable masked application audit event.

Provider scenarios​

PostgreSQL, MySQL and SQLite passed the complete generated Feature. SQL Server also passed the full Feature, including exact Top-N, native aggregates, optimistic locking and governance. When Roslyn's shared compiler is unreliable in automation, build with:

dotnet build -p:UseSharedCompilation=false

Failure checklist​

Check UserContext data-service initialization, the selected ADO.NET provider, generated relation metadata, database parameter types and the exact generated async terminal. Treat unknown dynamic fields, forbidden sorts and invalid paging as input errors rather than broad queries.

Continue with .NET advanced data operations for a composed search, relation graph, analytics, Facet, and audited update workflow.