Quick Start
This guide will walk you through creating a simple Ormed application with a User model. If you are integrating into an existing app, use Adopt Ormed In An Existing Project instead.
Prerequisites
- You completed Installation
- You can run
dart pub getanddart run build_runner buildin your app
What You’ll Learn
- How to scaffold runtime config with
ormed init - How models, migrations, seeders, and generated code connect
- How to boot
DataSourceand run basic CRUD
Step Outcome
By the end of this page, you should have:
- A generated runtime datasource scaffold
- A
Usermodel with generated ORM artifacts - A migration + seeder applied locally
- A runnable app that performs create/read/update/delete
Command Flow (One Pass)
dart run ormed_cli:ormed init
dart run build_runner build
dart run ormed_cli:ormed make:migration --name create_users_table --create --table users
dart run ormed_cli:ormed migrate
dart run ormed_cli:ormed make:seeder --name UserSeeder
dart run ormed_cli:ormed seed
dart run lib/main.dart
Scaffold the Project (CLI)
From your app root:
dart run ormed_cli:ormed init
This creates:
lib/src/database/config.dart(runtime datasource options)lib/src/database/datasource.dart(DataSource entrypoint)lib/src/database/migrations.dart(registry)
Optional:
ormed.yamlwhen you rundart run ormed_cli:ormed init --with-configlib/src/database/seeders.dartandseeders/database_seeder.dartwhen you rundart run ormed_cli:ormed init --with-seeders
Generated starter files:
- config.dart
- datasource.dart
- ormed.yaml (optional)
- migrations.dart
- seeders.dart (optional)
Generated runtime config (code-first default):
const String defaultDataSourceConnection = 'default';
/// Connections baked into this generated scaffold.
const List<String> generatedDataSourceConnections = <String>['default'];
DataSourceOptions buildDataSourceOptions({String? connection}) {
final env = OrmedEnvironment.fromDirectory(Directory.current);
final registry = bootstrapOrm();
final selectedConnection = (connection ?? defaultDataSourceConnection).trim();
switch (selectedConnection) {
case 'default':
final path = env.string(
'DB_PATH',
fallback: 'database/ormed_examples.sqlite',
);
return registry.sqliteFileDataSourceOptions(path: path, name: 'default');
default:
throw ArgumentError.value(
selectedConnection,
'connection',
'Unknown generated datasource connection. Expected one of: default',
);
}
}
Map<String, DataSourceOptions> buildAllDataSourceOptions() {
final options = <String, DataSourceOptions>{};
for (final connection in generatedDataSourceConnections) {
options[connection] = buildDataSourceOptions(connection: connection);
}
return options;
}
The recommended entrypoint for your application. It uses generated config helpers and works for both single and multi-connection scaffolds.
DataSource createDataSource({DataSourceOptions? options, String? connection}) {
return DataSource(options ?? buildDataSourceOptions(connection: connection));
}
Map<String, DataSource> createDataSources({
Map<String, DataSourceOptions> overrides = const {},
}) {
final sources = <String, DataSource>{};
for (final connection in generatedDataSourceConnections) {
final options =
overrides[connection] ?? buildDataSourceOptions(connection: connection);
sources[connection] = DataSource(options);
}
return sources;
}
Use this when you want explicit CLI connection blocks or multi-connection definitions:
# #region site-ormed-config
driver:
type: sqlite
options:
database: database.sqlite
migrations:
directory: lib/src/database/migrations
registry: lib/src/database/migrations.dart
ledger_table: orm_migrations
schema_dump: database/schema.sql
seeds:
directory: lib/src/database/seeders
registry: lib/src/database/seeders.dart
# #endregion site-ormed-config
These are the three pieces the CLI maintains: imports, the entry list, and buildMigrations().
// <ORM-MIGRATION-IMPORTS>
// </ORM-MIGRATION-IMPORTS>
final List<MigrationEntry> _entries = [
// <ORM-MIGRATION-REGISTRY>
// </ORM-MIGRATION-REGISTRY>
];
/// Build migration descriptors sorted by timestamp.
List<MigrationDescriptor> buildMigrations() =>
MigrationEntry.buildDescriptors(_entries);
Seed registries follow the same pattern: imports + registrations + a runnable entrypoint.
Generate this with ormed init --with-seeders, ormed init --only=seeders, or ormed make:seeder.
import 'database_seeder.dart';
// <ORM-SEED-IMPORTS>
// </ORM-SEED-IMPORTS>
final List<SeederRegistration> _seeders = <SeederRegistration>[
// <ORM-SEED-REGISTRY>
SeederRegistration(
name: 'AppDatabaseSeeder',
factory: (context) => AppDatabaseSeeder(context.connection),
),
// </ORM-SEED-REGISTRY>
];
Future<void> runProjectSeeds(
OrmConnection connection, {
List<String>? names,
bool pretend = false,
}) => runSeedRegistryOnConnection(
connection,
_seeders,
names: names,
pretend: pretend,
);
Future<void> main(List<String> args) =>
runSeedRegistryEntrypoint(args: args, seeds: _seeders);
Create Your Model
Create lib/src/models/user.dart:
// #region intro-model
import 'package:ormed/ormed.dart';
part 'user.orm.dart';
(table: 'users')
class User extends Model<User> {
const User({
required this.id,
required this.email,
this.name,
this.createdAt,
});
(isPrimaryKey: true, autoIncrement: true)
final int id;
final String email;
final String? name;
final DateTime? createdAt;
}
// #endregion intro-model
Generate ORM Code
Run the build runner:
dart run build_runner build
This creates user.orm.dart with the generated $User class and helpers.
Create a Migration
Create a migration for your table:
dart run ormed_cli:ormed make:migration --name create_users_table --create --table users
Edit the generated file in lib/src/database/migrations/ to add columns:
void up(SchemaBuilder schema) {
schema.create('users', (table) {
table.id();
table.string('name');
table.string('email').unique();
table.timestamps();
});
}
Apply the migration:
dart run ormed_cli:ormed migrate
Seed the Database
Create a seeder:
dart run ormed_cli:ormed make:seeder --name UserSeeder
This command bootstraps the seed scaffold automatically if it does not exist yet.
Add data in lib/src/database/seeders/user_seeder.dart:
Future<void> run() async {
await seed<User>([
{'name': 'John Doe', 'email': 'john@example.com'},
]);
}
Run the seeders:
dart run ormed_cli:ormed seed
Set Up the Database (SQLite)
- Setup
- CRUD
In your application code, use the generated createDataSource() helper to initialize the ORM.
import 'package:ormed/ormed.dart';
import 'src/database/datasource.dart'; // Generated by ormed init
void main() async {
// 1. Create the DataSource using generated runtime options
final ds = createDataSource();
// 2. Initialize connections
await ds.init();
// 3. Query your models
final users = await ds.query<User>().get();
print('Found ${users.length} users');
}
Use the generated tracked model ($User) with the repository and query builder:
Future<void> useOrm(DataSource dataSource) async {
final userRepo = dataSource.repo<$User>();
// Insert a user
final user = await userRepo.insert(
$User(id: 0, email: 'john@example.com', name: 'John Doe'),
);
print('Created user: ${user.id}');
// Query users
final users = await dataSource
.query<$User>()
.whereEquals('name', 'John Doe')
.get();
print('Found users: ${users.length}');
// Update a user
user.setAttribute('name', 'John Smith');
final updated = await userRepo.update(user);
print('Updated name: ${updated.name}');
// Delete a user
await userRepo.delete({'id': user.id});
print('User deleted');
}
Run Your App
dart run lib/main.dart
Output:
Created user: 1
Found users: 1
Updated name: John Smith
User deleted
Exact IDs/counts may differ, but you should see successful CRUD behavior without errors.
Next Steps
- Models Overview - move from demo fields to production model design
- Queries Overview - expand read patterns beyond basic CRUD
- Repository Pattern - structured writes and updates
- Migrations - schema evolution workflow