# Update Pipeline

> Implementation details for EF Core SaveChanges and the update pipeline. Use when changing CommandBatchPreparer, UpdateSqlGenerator, ModificationCommand, or related classes.

- Skill: `dotnet/update-pipeline` (Agent Skill)
- Install (CLI): `npx skillmds@latest add dotnet/update-pipeline`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dotnet/update-pipeline/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: .NET (Microsoft) (https://skillmd.com/u/dotnet)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/dotnet/update-pipeline

---


# Update Pipeline

Converts tracked entity changes into database INSERT/UPDATE/DELETE commands during `SaveChanges()`.

## Flow

`SaveChanges()` → `DetectChanges()` → `IDatabase.SaveChanges()`
  → `UpdateAdapter` creates `IUpdateEntry` list
  → `CommandBatchPreparer.BatchCommands()`
    → `ModificationCommand` per table row, composed of `ColumnModification` per column
      → `SharedTableEntryMap` is used to track entries mapped to the same row
    → Topological sort via Multigraph (FK dependency ordering)
    → Groups into `ModificationCommandBatch` (respects max batch size)
  → `UpdateSqlGenerator` generates SQL per batch
  → `BatchExecutor` executes all batches in a transaction
  → `StateManager.AcceptAllChanges()`

## Concurrency

Concurrency tokens → WHERE conditions on UPDATE/DELETE. `AffectedCountModificationCommandBatch` checks affected rows. Throws `DbUpdateConcurrencyException` on mismatch.

## Validation

- `SaveChanges()` returns expected affected row count
- Store-generated values propagate back to entities after INSERT/UPDATE
- `DbUpdateConcurrencyException` thrown when expected for stale data

