Quick Start
This guide walks through the generated-model path: a User model, migration, seeder, and typed queries. If you want to connect first and decide on models later, start with Direct Database Access. If you are integrating into an existing app, use Adopt Ormed In An Existing Project instead.
Before you start: You completed Installation; You completed the Code Generation tooling setup; You can run dart run ormed_cli:ormed as described in CLI Overview.
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;
}
Generate ORM Code
Run the build runner:
dart run build_runner build --delete-conflicting-outputs
This creates user.orm.dart with the generated $User class and helpers. For
watch mode, builder configuration, generated registry details, and verification
guidance, see Code Generation.
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