Fact
- Meaning
- A shaped value available to a relational program.
- Typical role
- A CLR object, database row, observation, API result, cached value, or materialized document.
Building Blocks
Portable relational programming for mapping, hydration, querying, and derived data across heterogeneous systems.
SQL showed the value of describing facts, relationships, filters, projections, and aggregations without prescribing the execution algorithm. Its usual boundary is a particular database catalog, server, dialect, and runtime.
Cohesive.Relations brings that declarative character into a general-purpose programming environment. Facts may come from PostgreSQL, Cosmos DB, a search index, an API, supplied CLR objects, observations, caches, or several sources together. The relational meaning stays portable while compilers, planners, and runtimes decide how to realize it.
A typed authoring surface can express a rooted derivation from a load and its related carrier into a search document:
var loadSearchDocument = Relation<LoadSearchDocument>
.From<Load>()
.Join<Carrier>((load, carrier) => load.CarrierId == carrier.Id)
.Select((load, carrier) => new LoadSearchDocument
{
LoadId = load.Id,
CarrierName = carrier.LegalName,
Amount = load.TotalAmount,
CarrierSafetyScore = carrier.SafetyScore
});The code defines the relation, not its physical execution. If Load and Carrier are available through one relational backend, a compiler can lower it to a single SQL query. If they live in different stores, the same definition can compile into a coordinated cross-source acquisition and hydration plan that batches lookups, joins the resulting facts, and produces the same LoadSearchDocument. The semantic contract stays fixed; only its realization changes.
Relational programming describes which facts, combinations, and derived values hold without reducing the program to one execution plan.
SQL offers the most familiar version of that idea, but normally assumes that the facts already live inside one database boundary. LINQ brings query structure into application code, but execution still depends on local sequence semantics or a provider's translation limits.
Cohesive.Relations keeps the semantic program above those choices. A logical source says that facts of a particular shape are available. It does not decide whether they arrive from memory, storage, a remote service, a cache, a materialized view, or a composed cross-source plan.
That separation gives relational definitions several forms of portability:
Cohesive relational programs connect several related concepts. A fact is a shaped value, often represented as an observation. A relation and a query use those facts differently.
A relationship such as Load.CustomerId → Customer identity is part of the semantic relation model. It records which shaped facts are connected and preserves the identity, direction, cardinality, requiredness, lineage, and dependency meaning of that edge.
Forward traversal from one Load.CustomerId may yield at most one customer. Inverse traversal may yield many loads. A required reference means the key must be present; it does not claim that the referenced observation currently exists.
An interpreter can realize that relationship in several ways:
An explicit join is still useful when two independently produced rowsets need to be correlated by a predicate. But it should only be treated as a declared relationship when it can preserve the complete relationship semantics.
Relations and queries share a logical algebra because both describe relational computation:
They differ in the contract wrapped around that shared logical graph:
The distinction is semantic rather than physical. Neither definition chooses a database, source placement, join algorithm, batching strategy, or execution runtime.
Aggregation is part of the query model, not a separate reporting API layered onto it. Filters, relationship traversals, joins, projections, and aggregations can share the same logical graph, so one query can expose several named views of the same predicate scope.
One predicate scope can feed several query results
Shared sources, joins, and predicates is the shared source for rows — projection, ordering, and paging, totals — count, sum, min, and max, by customer — grouping and filtered measures.
An aggregate node turns an input rowset into a shaped result. With no grouping fields it produces a singleton summary. With one or more grouping fields it produces a row per distinct key. Each aggregate assignment names its target field, operation, value expression, and optional filter.
Because aggregate output is itself a semantic shape, it can be projected, ordered, and paged like other query results. A single query might therefore return a page of delayed loads, an overall delayed-load count, and totals grouped by customer without duplicating the shared filter and join definitions.
An interpreter can lower the complete graph to a native SQL or backend aggregation when the target supports it. When data or capabilities are divided across sources, a planner can push compatible work into each source and compose the remaining aggregation. Unsupported semantics must be diagnosed rather than silently changed.
The canonical relationship catalog and relation/query IR are the sources of semantic truth. C# DSLs, generated definitions, importers, visual tools, and inference systems are producers of those portable models.
Relationships are persisted independently with stable identities. Relation and query definitions reference those relationships from a shared logical node graph. Versioned documents, strict validation, stable identifiers, and deterministic fingerprints make the model durable and inspectable outside one process or host language.
Inferred or convention-authored relations may begin as drafts. A draft can preserve candidate assignments, ambiguity, and explicit omissions without pretending that incomplete work is executable. Semantic acceptance checks output coverage, field existence, type compatibility, cardinality, presence, and nullability before producing an accepted relation.
Authoring
Typed DSLs, generated definitions, importers, visual tools, and Ari introduce relational intent.
Definition
Direct declarations or portable drafts capture logical structure, assignments, candidates, and omissions.
Validation
Shape-aware analysis checks coverage, types, cardinality, presence, nullability, and invariants.
Canonical IR
Versioned relationship catalogs and relation/query definitions retain stable identities and fingerprints.
Realization
Analyzers, compilers, planners, and runtimes execute, validate, visualize, document, or explain the model.
This keeps authoring uncertainty separate from accepted semantics and from runtime input availability.
The simplest DTO mapping copies values between two nearly identical shapes. Customer.Id maps to CustomerDto.Id; Customer.Name maps to CustomerDto.Name. The field names, types, and structures already agree, so the relation is little more than a set of direct assignments.
Real mappings quickly add structural nuance:
Even this is schema matching in a small, unusually convenient form: the two schemas live in the same codebase, their types are already known, and a developer can state each correspondence directly.
Ari extends Cohesive.Relations from explicitly authored mappings to inferred and governed matchings between arbitrarily complex, structurally distinct schemas. A source or target may be deeply nested, repeating, optional, encoded with unfamiliar names, organized around different concepts, or constrained by qualifiers and code sets. Ari analyzes those shapes as semantic graphs and proposes correspondences that may include renames, conversions, flattening, nesting, hierarchy changes, and value-dependent rules.
Those proposals retain confidence, supporting evidence, explanations, alternatives, and review state. A reviewer can accept, reject, constrain, or refine them without confusing inference uncertainty with executable semantics. Once accepted, the matching becomes a portable Cohesive.Relations definition that can be validated, persisted, interpreted, and reused across runtimes.
A relation or query declares logical sources, visible bindings, required and optional related inputs, predicates, projections, and output requirements. That semantic structure tells an interpreter which facts and fields are needed without dictating how they must be acquired.
An interpreter can then:
Adapters describe their capabilities and constraints. Compilers compare those capabilities with the relational program and produce a native, composed, constrained, overridden, or unsupported realization. They must not silently weaken semantics.
Authoring and inference produce semantic definitions. Compilers, analyzers, planners, and runtimes interpret them.
Producers
Semantic source of truth
Relationship catalog
Stable semantic edges with direction, cardinality, lineage, and dependency meaning.
Relation / query IR
A shared logical graph wrapped in distinct relation and query contracts.
Interpretations
An interpretation does not have to execute the definition. Validation, optimization, visualization, documentation generation, migration planning, dependency analysis, and lineage reporting are also realizations of the same semantic model.
Derived artifacts should retain provenance to the IR nodes and compiler decisions that produced them.
Cohesive.Relations overlaps with familiar mapping and query tools, but treats the relation or query as a portable semantic asset rather than making one runtime or transport its defining boundary.
Cohesive.Relations is not intended to replace every use of these tools. It is most useful when the mapping or query needs to remain inspectable and reusable across execution, hydration, persistence, API exposure, materialization, lineage, diagnostics, or multiple infrastructure targets.
Cohesive.Relations applies anywhere software needs to connect facts, derive a shaped result, request relational data, maintain a derived view, or explain why an output exists. Many of these use cases form projection models in the wider system graph.
Queries can span stores while preserving selection, batching, ordering, paging, and aggregation semantics.
Cohesive.Relations specifies what data a model or agent needs and how that data is loaded, joined, transformed, and projected. Agent behavior, tool use, planning, and orchestration are concerns for Cohesive.Semantics, not the relation model.
A relation or query can explain more than whether it is valid. Because its required facts, relationships, predicates, result branches, and capability requirements remain explicit, a planner can show both why data is needed and why a particular realization was selected.
Because mappings and projections are represented as derivations, missing inputs can be explained instead of reduced to a mapper failure:
Cannot derive LoadSearchDocument.CarrierName.Required premises Load.CarrierId = "carrier-123" Carrier.Id = "carrier-123"Available: Load.CarrierIdMissing: Carrier with Id "carrier-123"The model keeps three forms of incompleteness separate:
Missing, null, absent, unavailable, failed, and not requested are also distinct states. Structured diagnostics can therefore support applications, tests, deployment gates, index-management tools, and developer tooling.
Plan explanations connect the semantic definition to its physical realization. They can show:
Requested: LoadSearchDocument.CarrierNameRequires: Carrier.LegalName Load.CarrierId → Carrier.IdSelected plan: Read Load.Id, Load.CarrierId, and Load.TotalAmount from Cosmos Batch distinct CarrierId values Read matching Carrier facts from PostgreSQL Hash join in application memory Project LoadSearchDocumentWhy: Load and Carrier do not share a native join boundary. Batched loading preserves the declared relationship with two source reads.Like a database EXPLAIN result, this traces how a logical request becomes a physical plan. For a portable relation or query, that plan may also include backend capability matching, cross-source data loading, and composed execution.
Most systems accumulate mapping code, repository hydration, query builders, SQL strings, API response shaping, UI filters, search documents, reporting logic, integration transforms, and index-maintenance jobs as separate artifacts. Each artifact embeds part of the same relational meaning, usually without shared identity or provenance.
Cohesive.Relations makes that meaning first-class.
The payoff is not one universal runtime. It is one portable source of relational meaning that can be authored, inferred, persisted, validated, inspected, and interpreted without losing the distinction between a reusable relation and an invoked query.
Define the relational program once. Interpret it as a mapper, query, hydration plan, materialized view, index synchronizer, lineage report, or explanation while retaining provenance to the semantic source.