Materialised Views
This page is part of the documentation for Orleans.Lattice 9.9.0 (release line 9.9), built 2026-10-04. It is also published as markdown, with every table and list, at README.md, and llms.txt lists every page.What it shows
A materialised view is an asynchronous, eventually-consistent projection of a
source tree, maintained by tailing that tree's write-ahead log. This sample
declares two views over a people tree at startup and shows each converging to
reflect source writes:
- A filter / re-project view
adultsthat keeps only people withAge >= 18. - An aggregation view
age-sum-by-citythat sumsAgegrouped byCity.
It seeds five people, waits for the views to catch up, then mutates the source (adds an adult and ages a child past 18) and shows both views re-converging - all without ever writing to a view directly.
Run it
dotnet run --project samples/MaterialisedViews
Expected output
Silo starting... ready.
Writing source people:
Alice (age 34, London)
Bob (age 12, London)
Carol (age 27, Paris)
Dan (age 9, Paris)
Eve (age 41, London)
After initial seed - views converged to source:
'adults' view (3 keys, lag 0):
Alice (age 34)
Carol (age 27)
Eve (age 41)
'age-sum-by-city' aggregate:
London: sum(age) = 87
Paris: sum(age) = 36
Mutating source: add Frank(52, Paris); Bob turns 18 (London).
After mutation - views re-converged:
'adults' view (5 keys, lag 0):
Alice (age 34)
Bob (age 18)
Carol (age 27)
Eve (age 41)
Frank (age 52)
'age-sum-by-city' aggregate:
London: sum(age) = 93
Paris: sum(age) = 88
When to use
- You need a continuously-maintained secondary index, filtered subset, or rolled-up aggregate of a tree without recomputing it on every read.
- Consumers can tolerate eventual consistency (bounded apply lag behind the source).
When not to use
- When you need the value the instant the write commits - a view lags the source. Read the source tree directly for read-your-writes semantics.
- Views are read-only and derived. Attempting to write to a
view-*tree directly through the publicILatticesurface is rejected with anInvalidOperationException- change the source and let the view converge. A direct content read of aview-*tree throughILatticeis rejected the same way, because a rebuild can swap the view's active generation under a raw handle: read through theILatticeViewhandle thatILatticeViewFactoryreturns, as this sample does.
Notes
- The views are declared at startup (
AddLatticeViews(...)) so their maintainers come online with the host before any writes.WaitForSourceHeadAsyncmakes the sample deterministic by blocking until the applied frontier reaches the source head; production readers typically just tolerate the small apply lag.