RoomSharp.Cli 0.5.5

dotnet tool install --global RoomSharp.Cli --version 0.5.5
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local RoomSharp.Cli --version 0.5.5
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=RoomSharp.Cli&version=0.5.5
                    
nuke :add-package RoomSharp.Cli --version 0.5.5
                    

RoomSharp CLI

A production-grade command-line tool for RoomSharp ORM to scaffold code, manage migrations, and export schemas with safety and validation.

NuGet License


Overview

RoomSharp CLI is a .NET global tool that provides:

  • Scaffolding: Entities, DAOs, Database, Manual & Auto Migrations
  • Runtime migrations: Apply and track schema versions
  • Schema export: Dump schema for documentation and CI
  • Strict validation: C#/SQL identifiers, version windows, file safety
  • Multi-provider support:
    • SQLite (built-in)
    • PostgreSQL
    • MySQL
    • SQL Server

Installation

After publishing to NuGet:

dotnet tool install -g RoomSharp.Cli

Verify:

room --version
room --docs   # opens CLI docs page
room --help

Quick Start

Run these commands inside an existing C# project that references RoomSharp.

dotnet tool install -g RoomSharp.Cli

# Generate config file for this project
room make:config --provider sqlite --connection "Data Source=app.db" --ns MyApp.Data

# Create new entity (entities are C# classes representing database tables)
room make:entity User --table=users

# Create new DAO (data access objects)
room make:dao User --entity=User

# Create new database class (abstract base class for RoomDatabase)
room make:database AppDatabase --version=1 --entities=User

# Apply migrations and create the database (auto-builds the project)
room migrate:up -b

Command Reference

Usage: room <command> [options]

Flags:
  --version           Show CLI version
  --docs              Open CLI docs
  -i, --interactive   Launch interactive mode (TUI)
  -b, --build         Auto-build project before running command
  -r, --release       Build in Release mode (use with -b)

Scaffolding Commands:
  make:entity <Name> [--path=...] [--table=...] [--ns=...] [--force] [--dry-run]
  make:dao <Name> [--entity=...] [--path=...] [--table=...] [--entity-ns=...] [--ns=...] [--force] [--dry-run]
  make:database <Name> [--version=1] [--entities=...] [--path=...] [--ns=...] [--force] [--dry-run]
  make:migration <Name> [--from=1] [--to=2] [--path=...] [--ns=...] [--force] [--dry-run]
  make:auto-migration <Name> [--path=...] [--ns=...] [--force] [--dry-run]
  make:seeder <Name> [--entity=...] [--order=10] [--path=...] [--ns=...] [--force] [--dry-run]
  make:repository <Entity> [--path=...] [--ns=...] [--force] [--dry-run]
  make:view <Name> [--view=...] [--query=...] [--path=...] [--ns=...] [--force] [--dry-run]
  make:converter <Name> [--from=Type] [--to=Type] [--path=...] [--ns=...] [--force] [--dry-run]
  make:config [--provider=...] [--connection=...] [--ns=...] [--force] [--dry-run]

Migration Commands: (use -b to auto-build before running)
  migrate:up [--to=N] [-b] [--provider=...] [--connection=...] [--fallback-destructive]
  migrate:status [-b] [--provider=...] [--connection=...]
  migrate:timeline [-b] [--provider=...] [--connection=...]  (visual history)
  migrate:plan [--to=N] [-b] [--provider=...] [--connection=...]
  migrate:verify [-b] [--provider=...] [--connection=...]
  migrate:rollback [--to=N] [--steps=N] [-b] [--force]  (requires IReversibleMigration)
  migrate:set-version --to=N [--provider=...] [--connection=...] --force   (DANGEROUS)

Database Commands: (use -b to auto-build before running)
  database:drop [--provider=...] [--connection=...] [--force]
  database:reset [-b] [--provider=...] [--connection=...] [--force] [--fallback-destructive]
  database:seed [-b] [--env=...] [--only=A,B] [--skip=C] [--force] [--plan] [--dry-run]
               [--allow-production] [--continue-on-error] [--provider=...] [--connection=...]
  db:backup [--out=path] [--provider=...] [--connection=...]
  db:restore --from=path [--provider=...] [--connection=...] [--force]
  db:compare --target=<connection-string> [-b] [--provider=...] [--connection=...]

Inspection Commands:
  info                Show project and database info
  doctor              Run health checks on project configuration
  db:tables           List all tables with row counts
  db:stats            Show database statistics (size, rows, indexes)
  generate:diagram    Generate ERD (Mermaid/DBML)
  db:describe <Table> Show table structure (columns, types, keys)

Schema Commands:
  schema:export [--out=path] [--sql] [-b] [--provider=...] [--connection=...]
  schema:validate [--schema=path] [--provider=...] [--connection=...]

Query Command:
  query <SQL> [--format=table|json|csv] [--max-rows=100] [--file=path] [--allow-writes]

Global Flags:
  --provider          Override provider (sqlite|pgsql|mysql|sqlserver)
  --connection        Connection string (required for runtime commands)
  --config            Path to room.config.json
  --force             Overwrite files / skip confirmation / force re-run
  --dry-run           Preview without writing files or executing

Project Requirements

The CLI must be run inside a C# project that references RoomSharp. It will refuse execution otherwise.

Runtime commands (migrate:*, schema:export) require:

  • A valid RoomDatabase implementation
  • A built project (dotnet build)
  • Provider + connection string via config or flags

Configuration (room.config.json)

Optional but recommended. Place at the project root.

Once configured, you no longer need to pass --provider and --connection flags with every command β€” the CLI reads them automatically from your config file.

{
  "provider": "sqlite|pgsql|mysql|sqlserver",
  "connectionString": "Data Source=room.db",
  "buildConfiguration": "Debug",
  "paths": {
    "entities": "Data/Models",
    "daos": "Data/Daos",
    "database": "Data/Database",
    "migrations": "Data/Migrations",
    "autoMigrations": "Data/Migrations/Auto",
    "schema": "Data/Schemas",
    "seeders": "Data/Database/Seeders",
    "views": "Data/Views",
    "converters": "Data/Converters",
    "repositories": "Data/Database/Repositories"
  },
  "namespaceRoot": "MyApp.Data"
}

πŸ’‘ Quick Generate: room make:config --provider sqlite --connection "Data Source=room.db" --ns MyApp.Data

Connection String References

Instead of hardcoding connection strings, you can reference external sources:

From appsettings.json
{
  "connectionString": "$appsettings:ConnectionStrings:DefaultConnection"
}

This reads from appsettings.json (or appsettings.{ASPNETCORE_ENVIRONMENT}.json if exists):

// appsettings.json
{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=app.db"
  }
}
From Environment Variables
{
  "connectionString": "$env:DATABASE_URL"
}
# PowerShell
$env:DATABASE_URL = "Data Source=app.db"
room migrate:status -b

# Bash
export DATABASE_URL="Data Source=app.db"
room migrate:status -b

Build Configuration

Control whether --build uses Debug or Release:

{
  "buildConfiguration": "Release"
}

Or use the -r / --release flag to override:

room migrate:up -b -r   # Forces Release build

SQLite Smart Path Resolution

For SQLite provider, the CLI intelligently searches for database files when only a filename is provided:

{
  "provider": "sqlite",
  "connectionString": "Data Source=app.db"
}

Search Order:

  1. Project root: ./app.db
  2. Debug output: bin/Debug/net*/app.db
  3. Release output: bin/Release/net*/app.db

If the file doesn't exist, it will be created in the project root.

Note: Full paths (absolute or explicit relative) are used as-is without searching.

Generate it fast:

room make:config --provider sqlite --connection "Data Source=room.db" --ns MyApp.Data

Global Flags

Flag Description
--provider Override provider
--connection Override connection string
--config Path to room.config.json
-b, --build Auto-build project before running command
-r, --release Build in Release mode (use with -b)
--force Overwrite files
--dry-run Preview without writing
--fallback-destructive Allow destructive fallback

Auto-Build Flag

The -b / --build flag automatically builds your project before running commands that require a compiled assembly:

# Instead of:
dotnet build
room migrate:status

# Just use:
room migrate:status -b

Output:

β ‹ Building project (Debug)... (2.1s)
βœ“ Build succeeded (3.2s)

Current version : 1
Target version  : 3
Pending migrations:
  β€’ Migration_1_2 (1 β†’ 2)
  β€’ Migration_2_3 (2 β†’ 3)

Build Configuration

By default, -b builds in Debug mode. To build in Release:

# Method 1: CLI flag
room migrate:up -b -r
room migrate:up -b --release

# Method 2: room.config.json
{
  "buildConfiguration": "Release"
}

Priority: CLI flag -r takes precedence over buildConfiguration in config.


Scaffolding Commands

All scaffolding commands accept scoped names with / or \ to create nested folders under the configured path (including the derived namespace). For example:

room make:dao Api/V1/User
# => Data/Daos/Api/V1/IUserDao.cs (or under --path if provided)

Scaffolding commands normalize common RoomSharp naming conventions before writing files. The generated file and type use the normalized name, and the CLI prints Normalized name: ... when it changes the input.

Command Accepted input Generated type/file
make:dao User, UserDao, IUserDao IUserDao
make:database App, AppDatabase AppDatabase
make:seeder User, UserSeeder UserSeeder
make:repository User, UserRepository, IUserRepository IUserRepository and UserRepository
make:view UserStats, UserStatsView UserStatsView
make:converter DateOnly, DateOnlyConverter DateOnlyConverter

make:entity

room make:entity User --table=users

Generated Output (Exact):

using RoomSharp.Attributes;

namespace MyApp.Data.Models;

[Entity(TableName = "users")]
public sealed record User
{
    [PrimaryKey(AutoGenerate = true)]
    public long Id { get; set; }

    // TODO: add your columns here
}

make:dao

make:dao <Name> [--entity=Name] [--path=Data/Daos] [--table=...] [--entity-ns=...] [--ns=...] [--force] [--dry-run]
room make:dao User --entity=User --table=users
room make:dao UserDao
room make:dao IUserDao

Generated Output (Exact):

using RoomSharp.Attributes;
using MyApp.Data.Models;

namespace MyApp.Data.Daos;

[Dao]
public interface IUserDao
{
    [Insert]
    Task<long> Insert(User entity);

    [Update]
    Task<int> Update(User entity);

    [Delete]
    Task<int> Delete(User entity);

    [Query("SELECT * FROM users ORDER BY Id", NoTracking = true)]
    Task<List<User>> GetAllAsync();
}

make:database

room make:database AppDatabase --version=1 --entities=User

⚠️ Requires C# 12 for collection expressions.

using Microsoft.Extensions.Logging;
using RoomSharp.Abstraction;
using RoomSharp.Attributes;
using RoomSharp.Core;
using MyApp.Data.Models;
using MyApp.Data.Daos;

namespace MyApp.Data.Database;

[Database(Version = 1, Entities = [typeof(User)])]
public abstract class AppDatabase(
    IDatabaseProvider provider,
    ILogger logger
) : RoomDatabase(provider, logger)
{
    public abstract IUserDao UserDao { get; }
}

make:migration

room make:migration Migration_1_2 --from=1 --to=2
using System.Threading;
using System.Threading.Tasks;
using RoomSharp.Migrations;

namespace MyApp.Data.Migrations;

public sealed class Migration_1_2 : IRoomMigration
{
    public int StartVersion => 1;
    public int EndVersion => 2;

    public string Id => "MyApp.Data.Migrations.Migration_1_2:1->2";
    public string Name => "Migration_1_2";

    private const string Body = """
        -- TODO: describe the migration deterministically (SQL text, notes, etc.)
        """;

    public string Checksum => MigrationChecksum.Sha256(Body);

    public async Task UpAsync(MigrationContext ctx)
    {
        await using var cmd = ctx.CreateCommand("""
            -- TODO: add your DDL/DML here
            """);

        await cmd.ExecuteNonQueryAsync(ctx.CancellationToken);
    }
}

make:auto-migration

room make:auto-migration AutoSpec_1_2
using System.Data.Common;
using RoomSharp.Migrations.Auto;

namespace MyApp.Data.Migrations.Auto;

[RenameTable(FromTableName = "old_table", ToTableName = "new_table")]
[AddColumn(TableName = "your_table", ColumnName = "new_column", ColumnDefinition = "INTEGER NOT NULL DEFAULT 0")]
[DeleteColumn(TableName = "your_table", ColumnName = "obsolete_column")]
[DeleteTable(TableName = "legacy_table")]
public sealed class AutoSpec_1_2 : IAutoMigrationSpec
{
    public void OnPostMigrate(DbConnection connection)
    {
        // Optional: data fixups after DDL
    }
}

Auto Migrations: Runtime vs CLI

Auto migrations are declared directly on the RoomDatabase class using the [AutoMigration] attribute.

They can be executed in two ways:

  • At runtime: when the application starts and initializes the database.
  • Via CLI: using room migrate:up, which loads the same compiled assembly and executes the same migration pipeline.

There is no separate migration logic for the CLI. The CLI and runtime share the exact same migration engine.


make:config

room make:config --provider sqlite --connection "Data Source=room.db" --ns MyApp.Data

Generates room.config.json using the current defaults or provided overrides.


make:seeder

room make:seeder <Name> [options]

Generates a seeder class implementing IRoomSeeder.

Options
Option Description
--entity=User Link to entity type (adds EntityType to attribute)
--order=10 Execution order (default: 10)
--path=... Override output path (default: paths.seeders from config)
--ns=... Override namespace
Examples
room make:seeder User --entity=User --order=10
# => Data/Database/Seeders/UserSeeder.cs

room make:seeder Api/V1/AdminSeeder --entity=User
# => Data/Database/Seeders/Api/V1/AdminSeeder.cs

room make:seeder TestData --path=Tests/Seeders
# => Tests/Seeders/TestDataSeeder.cs
Generated Code
using RoomSharp.Attributes;
using RoomSharp.Seeding;

namespace MyApp.Data.Database.Seeders;

[Seeder(EntityType = typeof(User), Order = 10, RunInTransaction = true, Repeatable = false)]
public sealed class UserSeeder : IRoomSeeder
{
    public string? SeedVersion => "1.0.0";

    public async ValueTask SeedAsync(SeederContext ctx)
    {
        // Idempotent seeding logic here
        ctx.LogMessage("UserSeeder executed successfully");
        await Task.CompletedTask;
    }
}

Runtime Migration Commands

⚠️ IMPORTANT: Runtime commands load your compiled assembly. If you modify code (entities, migrations, database), you MUST rebuild before running these commands to avoid unexpected behavior.

Build Requirements

Option 1: Manual Build

dotnet build
room migrate:status

Option 2: Auto-Build (Recommended)

room migrate:status -b        # Debug build
room migrate:status -b -r     # Release build

Runtime commands that require a built assembly:

  • migrate:up, migrate:status, migrate:plan, migrate:verify
  • database:reset, database:seed
  • schema:export, schema:validate

Runtime commands require both provider and connectionString (either from room.config.json or via flags).


migrate:status

room migrate:status

Sample output:

Current version : 0
Target version  : 3
Latest migration: 3
Pending migrations:
  - Migration_1_2 (1->2)
  - Migration_2_3 (2->3)

migrate:up

room migrate:up --to=3
  • Applies auto + manual migrations
  • Uses MigrationManager under the hood
  • Optionally allows destructive fallback with --fallback-destructive
  • Rebuilds schema via SchemaGenerator after migrations

migrate:plan

Prints the exact migration chain that would be applied (strict pathing: no gaps, no branching).

room migrate:plan --to=3

migrate:verify

Verifies applied migrations against their recorded checksums in __room_migrations.

room migrate:verify

migrate:set-version (DANGEROUS)

This does not roll back schema changes. It only edits __room_state for manual recovery scenarios.

room migrate:set-version --to=2 --force

Use only if you know exactly what you’re doing (prefer restoring from a backup in production).


Schema Export

room schema:export --out ./schema_export
  • Uses SchemaMigrationExporter to export schema for the active provider and version.
  • Includes [DatabaseView(Managed = true)] definitions in JSON and SQL exports.
  • Defaults to schema_export folder at project root if --out is not provided (or to the paths.schema value from room.config.json if present).

Raw SQL Export

room schema:export --sql --out ./schema_sql

Use --sql to export raw CREATE TABLE DDL statements instead of JSON. Useful for:

  • DBA reviews
  • CI/CD verification
  • Database documentation

Schema Validate

room schema:validate --provider=sqlserver --connection="..." --schema=./schema_export
  • Uses SchemaRuntimeValidator.EnsureSchema to validate the live database schema against exported files.
  • Validates managed database views from the compiled project, so missing or changed managed views are detected.
  • Defaults to schema_export folder at project root if --schema is not provided (or to the paths.schema value from room.config.json if present).

Inspection Commands

Commands for inspecting project configuration and database state.

info

Display project and database information:

room info

Sample Output:

β”Œ RoomSharp Project Info
β”‚
β”‚ Project
β”‚   Name            MyApp.csproj
β”‚   Root            C:\path\to\project
β”‚   Provider        sqlite
β”‚   Connection      βœ“ configured
β”‚   Namespace       MyApp
β”‚
β”‚ Paths
β”‚   Entities        Data/Models
β”‚   DAOs            Data/Daos
β”‚   Database        Data/Database
β”‚   Migrations      Data/Migrations
β”‚   Seeders         Data/Database/Seeders
β”‚
β”‚ Database
β”‚   Class           AppDatabaseImpl
β”‚   Schema Version  2
β”‚   Entities        3
β”‚   Current Version 2
β”‚   Migrations      1 total, 0 pending
β”‚   Tables          5
β”‚
β”” βœ“ Info retrieved

doctor

Run health checks on project configuration:

room doctor

Sample Output:

β”Œ RoomSharp Doctor
β”‚ β€’ room.config.json found
β”‚ β€’ Provider: sqlite
β”‚ β€’ Connection string configured
β”‚ β€’ RoomDatabase found: AppDatabaseImpl
β”‚     Entities: 3
β”‚     Version: 2
β”‚ β€’ Database connection successful
β”‚ β€’ Migrations up to date
β”‚
β”” βœ“ All checks passed

db:tables

List all tables in the database with row counts:

room db:tables

Sample Output:

βœ“ Found 3 table(s) (90ms)

β”Œ Database Tables
β”‚ Table                    Rows
β”‚ ─────────────────────────────
β”‚ __room_migrations           1
β”‚ __room_state                1
β”‚ users                     150
β”‚
β”” 3 table(s)

db:describe

Show table structure with columns, types, and keys:

room db:describe <TableName>
room db:describe users

Sample Output:

βœ“ Found 3 column(s) (91ms)

β”Œ Table: users
β”‚ Column          Type           Null    Key    Default
β”‚ ──────────────────────────────────────────────────────
β”‚ Id              INTEGER        YES     PK     NULL
β”‚ Name            TEXT           YES            NULL
β”‚ Email           TEXT           NO             NULL
β”‚
β”” 3 column(s)

db:stats

Display database statistics including size, table counts, and index information:

room db:stats

Sample Output:

βœ“ Statistics gathered (91ms)

β”Œ Database Statistics
  Provider:    SQLite
  Size:        36.0 KB
  Tables:      4
  Total Rows:  3
  Indexes:     3

  Table                        β”‚       Rows β”‚  Cols β”‚  Idx
  ────────────────────────────────────────────────────────
  __room_migrations            β”‚          1 β”‚     9 β”‚    1
  __room_state                 β”‚          1 β”‚     7 β”‚    0
  notes                        β”‚          1 β”‚     4 β”‚    1
β”” 4 table(s), 3 row(s)

generate:diagram

Generate an Entity-Relationship Diagram (ERD) in Mermaid or DBML format:

room generate:diagram [options]
Option Description
--output=path Save to file (prints to console if omitted)
--format=mermaid\|dbml Output format (default: mermaid)

Examples:

# Print Mermaid diagram to console
room generate:diagram

# Save DBML to file
room generate:diagram --output=schema.dbml --format=dbml

# Save Mermaid to file
room generate:diagram --output=docs/erd.md --format=mermaid

migrate:rollback

Rolls back migrations using the IReversibleMigration interface:

room migrate:rollback              # Roll back 1 step
room migrate:rollback --steps=3    # Roll back 3 steps
room migrate:rollback --to=5       # Roll back to version 5
room migrate:rollback --force      # Skip confirmation
Option Description
--to=N Roll back to specific version
--steps=N Roll back N steps (default: 1)
--force Skip confirmation prompt
-b Auto-build before running

⚠️ Requires IReversibleMigration: Only migrations implementing IReversibleMigration with DownAsync can be rolled back.


migrate:timeline

Displays a visual timeline of applied migrations:

room migrate:timeline

Sample Output:

β”Œ Migration Timeline
  Date             β”‚ Migration                        β”‚     Time β”‚ Status
  ─────────────────┼──────────────────────────────────┼──────────┼───────
  2024-12-15 10:30 β”‚ Migration_1_2                    β”‚    125ms β”‚ βœ“
  2024-12-18 14:15 β”‚ Migration_2_3                    β”‚     89ms β”‚ βœ“
  2024-12-20 09:00 β”‚ Migration_3_4                    β”‚     45ms β”‚ βœ—
     └─ Foreign key constraint failed...
β”” Current Version: 3

make:view

Creates a DatabaseView entity for mapping SQL views:

room make:view <Name> [--view=view_name] [--query="SELECT ..."] [--path=...] [--ns=...] [--force] [--dry-run]

Examples:

room make:view UserStats --view=user_stats
room make:view OrderSummary --query="SELECT u.Id, COUNT(o.Id) AS OrderCount FROM users u LEFT JOIN orders o ON u.Id = o.UserId GROUP BY u.Id"

Generated Output:

using RoomSharp.Attributes;

namespace MyApp.Data.Views;

[DatabaseView(ViewName = "user_stats", Query = "SELECT * FROM your_table")]
public sealed record UserStatsView
{
    public long Id { get; set; }
    // TODO: Add properties matching your view columns
}

make:converter

Creates a TypeConverter class for custom type mappings:

room make:converter <Name> [--from=Type] [--to=Type] [--path=...] [--ns=...] [--force] [--dry-run]

Examples:

room make:converter JsonConverter --from=MyModel --to=string
room make:converter DateOnlyConverter --from=DateOnly --to=string

Generated Output:

using RoomSharp.Converters;

namespace MyApp.Data.Converters;

public sealed class JsonConverter : TypeConverter<string, MyModel>
{
    public override MyModel FromProvider(string provider)
    {
        throw new NotImplementedException();
    }

    public override string ToProvider(MyModel model)
    {
        throw new NotImplementedException();
    }
}

Database Commands

⚠️ These commands require provider and connectionString. The CLI reads them from room.config.json when present, and command-line flags override config values. Build the project first for non-SQLite providers.

database:drop

room database:drop --provider=sqlite --connection="Data Source=app.db"
  • SQLite: Deletes the .db, -shm, -wal, and -journal files.
  • MySQL/PostgreSQL/SQL Server: Executes DROP DATABASE IF EXISTS.
  • Prompts for confirmation unless --force is used.

database:reset

room database:reset --provider=sqlite --connection="Data Source=app.db" --force

Combines database:drop + migrate:up for a fresh start during development.

db:backup

room db:backup --out=backup.bak
  • SQLite: Creates a consistent database copy with VACUUM INTO.
  • SQL Server: Runs through the project host and creates a native .bak backup.
  • MySQL and PostgreSQL backups should use provider-native tools until first-class CLI backup support is added.

For SQL Server, the backup path is read by the SQL Server service. A relative path such as backup.bak is resolved against SQL Server's default backup directory. An absolute path must be writable by the SQL Server service account.

db:restore

room db:restore --from=backup.bak --force
  • SQLite: Replaces the database file.
  • SQL Server: Runs through the project host and restores the native .bak file.

For SQL Server, a relative path such as backup.bak is resolved against SQL Server's default backup directory. An absolute path must be readable by the SQL Server service account.

db:compare

room db:compare --target="Server=.;Database=TargetDb;Trusted_Connection=True;TrustServerCertificate=True;" -b

Compares the configured source database against a target database using the same provider. The source connection comes from room.config.json unless overridden with --connection; the target is required because it identifies the second database.

--target also supports the same connection string references as config values, including $appsettings: and $env:.


Query Command

Execute SQL queries directly from the CLI with formatted output.

Note: This command is intended for diagnostics and reporting, not as a replacement for application-level data access.

room query <SQL> [options]
room query --file=queries/report.sql [options]

Options

Option Description
--format=table Output format: table (default), json, csv
--max-rows=100 Limit returned rows (default: 100)
--file=path Execute SQL from a file
--allow-writes Enable INSERT/UPDATE/DELETE/DROP operations

Examples

# Simple query
room query "SELECT * FROM users LIMIT 10"

# With JSON output
room query "SELECT id, name FROM users" --format=json

# Export to CSV
room query "SELECT * FROM orders" --format=csv > orders.csv

# Execute from file
room query --file=reports/monthly.sql --max-rows=500

# Write operations (requires --allow-writes)
room query "UPDATE users SET active = 1 WHERE id = 5" --allow-writes

Output Formats

Table (default):

+----+-----------+-------------------+--------+
| Id | Name      | Email             | Active |
+----+-----------+-------------------+--------+
| 1  | Ahmed     | ahmed@example.com | true   |
| 2  | Sara      | sara@example.com  | false  |
+----+-----------+-------------------+--------+

JSON:

[
  {"Id": 1, "Name": "Ahmed", "Email": "ahmed@example.com", "Active": true},
  {"Id": 2, "Name": "Sara", "Email": "sara@example.com", "Active": false}
]

CSV:

"Id","Name","Email","Active"
1,"Ahmed","ahmed@example.com","True"
2,"Sara","sara@example.com","False"

⚠️ Safety: Write operations (INSERT, UPDATE, DELETE, DROP, etc.) are blocked by default. Use --allow-writes to enable them.


database:seed

Advanced seeding with idempotency, dependency ordering, and production safety.

room database:seed [options]
Flags
Flag Description
--env=Development Environment filter (default: ASPNETCORE_ENVIRONMENT or Development)
--only=A,B Run only specified seeders
--skip=A,B Skip specified seeders
--force Force re-run even if already applied
--plan Show execution plan without running
--dry-run Preview mode - no actual execution
--allow-production Allow running in Production environment
--continue-on-error Continue running other seeders if one fails
Example
room database:seed --env=Development --plan
room database:seed --only=UserSeeder,RoleSeeder --force
room database:seed --skip=TestDataSeeder
Implementing a Seeder
using RoomSharp.Attributes;
using RoomSharp.Seeding;

[Seeder(EntityType = typeof(User), Order = 10, DependsOn = new[] { typeof(RoleSeeder) })]
public sealed class UserSeeder : IRoomSeeder
{
    public string? SeedVersion => "1.0.0"; // Change to trigger re-run

    public async ValueTask SeedAsync(SeederContext ctx)
    {
        var dao = ((AppDatabase)ctx.Database).UserDao;

        // Idempotent: check before insert
        if (!await dao.ExistsByEmailAsync("admin@local"))
        {
            await dao.InsertAsync(new User { Email = "admin@local", Role = "Admin" });
        }

        ctx.LogMessage("UserSeeder completed");
    }
}
Seeder Attribute Options
Property Description
EntityType Entity type this seeder populates (for documentation)
Order Execution order within same dependency level
DependsOn Seeder types that must run first
Environments Allowed environments (empty = all)
RunInTransaction Wrap in transaction (default: true)
Repeatable Can re-run based on SeedVersion hash (default: false)
Seeder Journal

The CLI tracks applied seeders in __room_seed_journal table:

Column Description
SeederId Full type name
Version SeedVersion value
AppliedAt Timestamp
Environment Environment name
AssemblyName Source assembly

Interactive Mode

Launch a menu-driven interface with the --interactive (or -i) flag:

room --interactive
room -i

Interactive Mode

The TUI guides you through:

  • Creating entities, DAOs, databases, migrations, and seeders
  • Running migrations
  • Seeding the database
  • Exporting schemas
  • Resetting the database

Providers

Provider Value Package
SQLite sqlite Built-in in RoomSharp
PostgreSQL pgsql RoomSharp.PostgreSql
MySQL mysql RoomSharp.MySql
SQL Server sqlserver RoomSharp.SqlServer

For non-SQLite providers, make sure you reference the corresponding RoomSharp provider package.


Safety & Validation

RoomSharp CLI is designed to be safe-by-default:

  • Refuses to run outside a RoomSharp-enabled C# project.
  • Validates:
    • C# identifiers for generated types and namespaces.
    • SQL identifiers for table names.
    • Migration version windows (to > from).
  • Prevents overwriting files unless --force is explicitly used.
  • --dry-run always shows intended writes without touching the filesystem.
  • Runtime commands will fail fast if:
    • Provider is missing (--provider or config).
    • Connection string is missing (--connection or config).
    • No RoomDatabase implementation is found in the built assembly.

Important Runtime Notes

The CLI loads your application assembly via reflection:

  • It searches for the .csproj closest to the working directory.
  • It determines the assembly name from <AssemblyName> or the project file name.
  • It looks under bin/Debug|Release/net* for the built DLL.
  • It then finds the first concrete type assignable to RoomDatabase.

If it cannot find the assembly or database type, it will emit:

Could not locate built assembly. Please run 'dotnet build' first (Debug or Release).
No RoomDatabase implementation found in assembly.

Always ensure:

dotnet build

runs successfully before migrate:* or schema:export.

πŸ’‘ Tip: Use -b flag to auto-build: room migrate:status -b


License

This project is licensed under the MIT License - see the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.5.5 115 5/10/2026
0.5.4 96 5/1/2026
0.5.3 94 4/30/2026
0.1.8 108 4/28/2026
0.1.7 105 4/27/2026
0.1.6 104 4/20/2026
0.1.5 144 1/15/2026
0.1.4 118 1/11/2026
0.1.3 118 1/3/2026
0.1.2 130 12/26/2025
0.1.1 198 12/19/2025

RoomSharp.Cli v0.5.3

   This release aligns RoomSharp.Cli with the RoomSharp v0.5.3 ecosystem.

   Starting with v0.5.3, RoomSharp uses synchronized versioning across ecosystem packages. Packages released as part of the same ecosystem update now share the same version number.

   RoomSharp.Cli previously followed an independent version line. Its last independent release was v0.1.8. The version jump to v0.5.3 is intentional and reflects ecosystem alignment, not a breaking change by itself.

   CLI highlights since v0.1.8:
   - Added database backup support via db:backup.
   - Added database restore support via db:restore.
   - Added schema comparison support via db:compare.
   - Added migration rollback support via migrate:rollback.
   - Added migration timeline visualization via migrate:timeline.
   - Added database statistics via db:stats.
   - Added ERD generation via generate:diagram.
   - Added scaffolding for DatabaseView entities via make:view.
   - Added scaffolding for TypeConverter classes via make:converter.
   - Added views, converters, and repositories paths to room.config.json.
   - Fixed MySQL transaction handling in rollback operations.
   - Added user-friendly version mismatch detection with actionable solutions.
   - Updated dependencies.

   See the changelog for full details.