Persistence as dumb IOThe adapter, and DBO is not the VO
No narration yet
Module 7 · Lesson 112 min

The adapter, and DBO is not the VO

Persistence is the outer layer, and its whole job is boring on purpose. An adapter implements a port and does IO: it maps the domain object to a database row, and saves. It does not validate, calculate, or call domain factories. Boring is the goal; interesting persistence code usually means domain logic leaked outward.

The adapter implements the port (persistence/FlightNotes/FlightNoteRepository.cs)
public sealed class FlightNoteRepository : IFlightNoteRepository
{
    private readonly FusionDbContext _dbContext;

    public FlightNoteRepository(FusionDbContext dbContext) => _dbContext = dbContext;

    [Trace]
    public async Task SaveMany(IReadOnlyCollection<FlightNoteVo> notes, CancellationToken cancellationToken)
    {
        _dbContext.FlightNotes.AddRange(notes.Select(FlightNote.From));
        await _dbContext.SaveChangesAsync(cancellationToken);
    }
}

The row it saves is a DBO (a database object), and this is a distinction Nest can blur: the DBO is NOT the value object. FlightNoteVo is the domain value object (behaviour, invariants, private ctor). FlightNote is a persistence record: EF attributes, an Id, audit columns, public setters. A mapper, FlightNote.From(vo), copies VO to DBO.

The DBO maps FROM the VO, no validation (persistence/Dbos/FlightNote.cs)
public static FlightNote From(FlightNoteVo note) =>
    new()
    {
        Id = MonotoneUuidV7.Next(),
        EjdpUniqueFlightKey = note.EjdpUniqueFlightKey,
        Body = note.Body
        // Audit fields intentionally omitted, filled by Postgres on INSERT.
    };
Practice

Try it yourself

Do

Trace one note through the layers

Walk a single note from request to row and name the boundary each hop crosses. Use the real files.

Tick every step to confirm you did it.

Recall

VO versus DBO

Two representations, know the difference.

What's the difference between FlightNoteVo and the FlightNote DBO, and what must the DBO's From mapper NOT do?

Quiz

What the adapter may do

Which of these is legitimate work for a persistence adapter?