Migrations & Seed Data
Once your models are defined, you need to create the corresponding database tables and optionally populate them with initial data.
Create migrations
Migrations allow you to evolve your database schema over time. You can generate migration files using the ormed CLI.
dart run ormed_cli:ormed make --name create_genres --create --table genres
dart run ormed_cli:ormed make --name create_movies --create --table movies
These commands generate Dart files in lib/src/database/migrations/. You can then define your columns using a fluent schema builder.
- Genres migration
- Movies migration
schema.create('genres', (table) {
table.id();
table.string('name');
table.text('description').nullable();
table.timestamps();
});
schema.create('movies', (table) {
table.id();
table.string('title');
table.integer('release_year');
table.text('summary').nullable();
table.string('poster_path').nullable();
table.integer('genre_id').nullable();
table.foreign(
['genre_id'],
references: 'genres',
referencedColumns: ['id'],
onDelete: ReferenceAction.setNull,
);
table.timestamps();
});
Seed with DTOs
Seeding is the process of populating your database with initial data, which is useful for development and testing. In Ormed, we use the generated DTOs to ensure our seed data matches our model definitions.
Individual Seeders
We create separate seeders for each model to keep things organized.
- Genre seeder
- Movie seeder
final repo = connection.context.repository<Genre>();
await repo.insertMany([
GenreInsertDto(
name: 'Drama',
description: 'Character-driven storytelling with emotional stakes.',
),
GenreInsertDto(
name: 'Science Fiction',
description: 'Speculative worlds, future tech, and big ideas.',
),
GenreInsertDto(
name: 'Mystery',
description: 'Twists, clues, and investigative tension.',
),
]);
final genres = await connection.query<Genre>().get();
final drama = genres.firstWhere((g) => g.name == 'Drama').id;
final sciFi = genres.firstWhere((g) => g.name == 'Science Fiction').id;
final mystery = genres.firstWhere((g) => g.name == 'Mystery').id;
final repo = connection.context.repository<Movie>();
await repo.insertMany([
MovieInsertDto(
title: 'City of Amber',
releaseYear: 2006,
summary: 'Two teens uncover the secrets of an underground city.',
genreId: sciFi,
),
MovieInsertDto(
title: 'Glass Letters',
releaseYear: 2019,
summary: 'A detective pieces together a locked-room mystery.',
genreId: mystery,
),
MovieInsertDto(
title: 'Ashes in Winter',
releaseYear: 2014,
summary: 'A family confronts loss and renewal after a storm.',
genreId: drama,
),
]);
// Demonstrate update DTOs (fix a typo in a summary).
await repo.update(
const MovieUpdateDto(
summary: 'A detective reconstructs a locked-room mystery.',
),
where: {'title': 'Glass Letters'},
);
The Root Seeder
The DatabaseSeeder is the entry point that coordinates all other seeders.
- Database seeder
await call([GenreSeeder.new, MovieSeeder.new]);
Run migrations + seeds
Finally, apply the migrations to create the tables and run the seeders to populate them.
# Apply all pending migrations
dart run ormed_cli:ormed migrate
# Run the database seeders
dart run ormed_cli:ormed seed