Point in time: AsOf
What did this policy look like when the claim was filed?
cs
var policy = await db.Policies
.AsOf(claim.OccurredAt)
.SingleOrDefaultAsync(p => p.Id == claim.PolicyId);AsOf(instant) reads from the history table instead of the main table, and keeps the version whose period contains instant:
sql
valid_from <= @instant AND valid_to > @instantThat is the version the database held at that moment. A policy that did not exist yet at instant, or had already been deleted, returns nothing.
Composing
Everything after AsOf composes as usual and becomes one SQL query:
cs
var largeDrafts = await db.Policies
.AsOf(endOfLastQuarter)
.Where(p => p.Status == PolicyStatus.Draft && p.Premium > 10_000m)
.OrderByDescending(p => p.Premium)
.Select(p => p.Number)
.ToListAsync();The instant is a query parameter, so queries at different instants share one compiled query and one query plan.
The generated SQL
For a filter on Status and a descending order on Number (from Hindsight's test suite):
sql
-- @AsOfUtc='2026-01-01T09:00:00.0000000Z' (DbType = DateTime)
SELECT p.id, p.metadata, p.number, p.premium, p.status, p.tags
FROM policies_history AS p
WHERE p.valid_from <= @AsOfUtc AND p.valid_to > @AsOfUtc AND p.status = 'Active'
ORDER BY p.number DESCRules
AsOfmust be the first operator, directly on theDbSet:db.Policies.AsOf(t).Where(…), notdb.Policies.Where(…).AsOf(t).- The result is no-tracking and read-only.
Includethrows.
See Rules for historical queries for the details and the alternatives.