DDD layers and CQRSQueryStore reads, Repository writes
No narration yet
Module 9 · Lesson 213 min

QueryStore reads, Repository writes

Reads and writes live in different classes, and the naming tells you which is which. A QueryStore does read-only queries: method names start with Get, and every query is .AsNoTracking() (it never intends to mutate, so it skips EF's change tracker). A Repository loads entities for an operation and saves them: Load* to read-for-write, Save*/MarkAs* to write. Anti-pattern #6: don't mix AsNoTracking reads and writes in one class, and don't put Get* on a repository or Load* on a query store.

Read side: AsNoTracking, Get* (real DecisionQueryStore)
public sealed class DecisionQueryStore : IDecisionQueryStore
{
    public async Task<IReadOnlySet<string>> GetDecidedFlightIdentities()
    {
        var keys = await _dbContext.FlightDisruptionCostCalcs
            .AsNoTracking()                                  // read-only, no change tracking
            .Where(x => x.DecidedAtUtc != null && x.RevokedAtUtc == null)
            .Select(x => x.EjdpUniqueFlightKey)
            .ToListAsync();
        return keys.ToHashSet(StringComparer.OrdinalIgnoreCase);
    }
}
Practice

Try it yourself

Quiz

Where does the method go

You need a method that returns a list of decided snapshots for a date range, read-only, for a list view. Where does it belong and what marks it?

Recall

Why AsNoTracking

State the reason, not just the rule.

Why does every method in a QueryStore call .AsNoTracking()?