How-to guide
Generate entities and migrations
Generate typed entities from a live database, or turn entity changes into reviewable, versioned migrations, with one tool for every engine.
Prerequisites
- The Kiwi shell with the Kiwi ORM Tooling CLI registered
- A reachable database and its connection string
Tip
Included in the free, source-available edition. See Editions and features.
The tooling covers the whole schema lifecycle (generate, migrate, detect drift, preview and roll back) in the same way for every supported engine, so there is no per-provider tooling to learn. Nothing is a black box: both directions produce files you can read, review and commit.
Register the tool#
The CLI is a library of declarative commands that runs inside the Kiwi shell. Put a kiwi.product.json next to the built assembly:
{ "productKey": "orm", "name": "Kiwi ORM Tooling", "version": "1.0.0", "cliAssembly": "Kiwify.Kiwi.ORM.Tooling.Cli.dll" }
Then run kiwi register <folder>. Commands take the form kiwi orm <command>, for example kiwi orm scaffold --connection .... The migration commands are hyphenated, such as kiwi orm model-apply. (The shell targets .NET 8 and the tool .NET 10, so until the library is multi-targeted run with DOTNET_ROLL_FORWARD=LatestMajor.)
Data-first: database to code#
kiwi orm list-providers # supported engines, NuGet packages and connection templates
kiwi orm install-driver --provider postgresql # restore the ADO.NET driver (cached in ~/.kiwi-orm/drivers)
kiwi orm scaffold --provider postgresql --connection "<connection-string>" # read the live database into kiwi-schema.json
kiwi orm generate --namespace MyApp.Data --context-group Sales # generate classes from kiwi-schema.json
- Scaffold reads tables, columns, primary and foreign keys, indexes and (optionally) procedures into
kiwi-schema.json, a reviewable and editable file. - Generate turns that file into typed C#: one
Entity<T>subclass per table, properties usingSetAndNotify,[TableInfo](schema-qualified),[ColumnInfo]with key, identity, type and default, foreign keys as[ForeignKey]/ColumnReferencewithEntityRef<>andEntityList<>navigations, and[StoredProcInfo]classes for procedures. Tables without a primary key are generated with a warning.
Every option is listed in the CLI reference. generate needs no database connection. --context-group sets the name written into [DbContextObject("...")]; register that group with AddDbObjects("<group>") in your context.
Model-first: code to database#
kiwi orm model-init --project MyApp --provider postgresql --namespace MyApp.Data
kiwi orm model-add-change --description AddMiddleName --assembly bin/Debug/net8.0/MyApp.dll
kiwi orm model-apply --connection "<connection-string>" --dry-run # preview the SQL
kiwi orm model-apply --connection "<connection-string>" # apply pending blocks transactionally
kiwi orm model-status --connection "<connection-string>" # applied and pending blocks
kiwi orm model-verify --connection "<connection-string>" # detect drift from changes made outside migrations
kiwi orm model-rebuild # rebuild schema.json from the migration file (no database)
kiwi orm model-rollback --connection "<connection-string>" --confirm # roll back the last applied block
add-changereads the entity classes, diffs them against the snapshot and generates the matching provider-specific SQL.- Renames are never guessed. A dropped plus added column that looks the same only produces a Possible rename note. Confirm it with
--rename "Orders=Sales;Items.Name=Title"to getRENAMEstatements that keep data, keys and indexes. applyruns pending blocks transactionally and records them in the__KiwiSchemaMigrationstable.--dry-runshows what would run.verifycompares the live database withschema.jsonand reports drift, meaning changes made outside a migration.rollbackruns the rollback statements of the last applied block (--confirmis required) and marks it-- REVERTED:.--allow-data-lossis needed when existing rows no longer fit the old column definitions.
The migration file#
Migrations are append-only and git-friendly. Each block holds the forward SQL, then rollback SQL as comments in reverse order:
-- MIGRATION: <id>
-- Author: <author>
-- MODEL: {compact JSON of the structured operations}
<forward SQL, with "-- NOTE:" / "-- WARNING:" lines where something cannot be automated>
-- ROLLBACK: <id>
-- <undo statements, last forward step first, commented out>
-- END ROLLBACK
- The
-- MODEL:line lets the snapshot be rebuilt exactly from the migration history, which resolves merge conflicts automatically. Hand-written blocks fall back to replaying the SQL. - Every destructive statement (
DROP TABLE,DROP COLUMN) ships commented out until you deliberately uncomment it. - Reverted blocks are ignored by rebuild and never re-applied.
Defaults and limits#
Default value changes are diffed and migrated (and SQLite emits a note, since it cannot alter a default). Views are not read from the database. See Common problems for engine-specific limitations.
Expected result
- Entities generated from a database, or a migration generated, previewed and applied