Architecture
SmartData at 30,000 feet — projects, layers, and how they fit together.
SmartData is a .NET 10 data framework built around three ideas: data lives in auto-migrating entities, business logic lives in typed stored procedures, and every client–server call is one binary RPC to POST /rpc. No controllers, no service layers, no per-endpoint routing.
Project layers
All projects target net10.0. Every library project publishes a NuGet package; SmartData.Cli also publishes a self-contained sd executable.
Arrows point toward dependencies:
┌──────────────────────────────────────────────────┐
│ SmartData.Core binary serializer + │
│ protocol models │
│ SmartData.Contracts shared result DTOs │
└──────────────────────────────────────────────────┘
▲ ▲
│ │
┌─────────────┴──────────────┐ ┌──────────┴─────────────┐
│ SmartData.Server │ │ SmartData.Client │
│ AutoRepo, procs, │ │ HTTP client for │
│ scheduler, session, │ │ POST /rpc │
│ metrics, backups │ └──────────┬─────────────┘
│ ├─ Server.Sqlite │ ▲
│ └─ Server.SqlServer │ │
└────────────┬───────────────┘ ┌──────────┴─────────────┐
▲ │ SmartData.Cli │
│ │ `sd` single-file │
┌────────────┴───────────────┐ │ executable │
│ SmartData.Console │ └────────────────────────┘
│ embedded admin UI │
└────────────────────────────┘
Client and Cli never reference Server — they're pure RPC consumers. Console is an in-process admin surface and does depend on Server.
| Project | Role | Reference |
|---|---|---|
| Core | Binary serializer, CommandRequest / CommandResponse, VoidResult. Zero dependencies. |
smartdata-core |
| Server | AutoRepo ORM, procedure discovery + executor, RPC router, session/auth, metrics, backup, scheduler. | smartdata-server |
| Server.Sqlite | SQLite provider — file-based databases, FTS5, WAL journal. | smartdata-server-sqlite |
| Server.SqlServer | SQL Server provider — full-text via CONTAINS + catalog, IDENTITY columns, native ALTER TABLE. | smartdata-server-sqlserver |
| Client | Lightweight HTTP client wrapping binary RPC calls. | smartdata-client |
| Cli | Self-contained sd executable for database, table, data, backup, import/export operations. |
smartdata-cli |
| Console | Embedded MVC admin UI mounted at /{prefix}/console/ — tables, query builder, users, backups, schedules, metrics. |
smartdata-console |
The three big ideas
Entities → AutoRepo
Entities are plain classes with LinqToDB [Table] / [Column] / [PrimaryKey, Identity] attributes, plus SmartData's stackable [Index] / [FullTextIndex]. With SchemaMode.Auto (default), first use of each entity compares the class to the live database and adds tables, columns, and indexes. Auto mode never drops or renames columns — renaming a property creates a new column and leaves the old one in place. Use SchemaMode.Manual in production unless you understand that.
See: Entities.
Procedures own business logic
Business logic lives in classes extending StoredProcedure<TResult> (sync) or AsyncStoredProcedure<TResult> (async). services.AddStoredProcedures(assembly) scans for implementations at startup. Public properties on the class are parameters, bound by name and case-insensitive. Naming convention: CustomerList auto-registers as usp_customer_list; framework procedures use the sp_ prefix. Errors use RaiseError(id, msg, severity) — IDs 0–999 are system, 1000+ are yours.
See: Procedures, Database context.
One endpoint, binary
All traffic is POST /rpc with content type application/x-binaryrpc. Request and response bodies are BinarySerializer-encoded CommandRequest / CommandResponse; the Args dictionary inside the request is itself binary-serialized (double-serialized). There is no JSON and browser devtools cannot inspect payloads — for debugging, call CommandResponse.GetDataAsJson() server-side. app.UseSmartData() wires the endpoint plus GET /health in one line.
See: Binary RPC.
Request lifecycle
Client Server
│ │
│ POST /rpc (application/x-binaryrpc) │
│ BinarySerialize(CommandRequest) │
├─────────────────────────────────────────▶│
│ │ CommandRouter
│ │ ├─ deserialize request
│ │ └─ validate token
│ │ │
│ │ ▼
│ │ ProcedureExecutor
│ │ ├─ resolve from catalog
│ │ ├─ create DI scope
│ │ ├─ instantiate procedure
│ │ ├─ bind params (by name)
│ │ └─ Execute(ctx, ct)
│ │ │
│ │ ▼
│ BinarySerialize(CommandResponse) │ serialize result
│◀─────────────────────────────────────────┤
│ │
Every call gets a fresh scoped IDatabaseContext with a pooled connection. Procedures do not run inside an implicit transaction — use ctx.BeginTransaction() + tx.Commit() for multi-step atomicity.
Two caller interfaces separated by trust: IProcedureService runs under framework authority (UserId = "system", auth gate bypassed) for schedulers and trusted server-side code; IAuthenticatedProcedureService enforces session auth and is wired automatically for /rpc and user-facing controllers. Don't reach around the auth gate — route unauthenticated work through IProcedureService.
Provider abstraction
A provider implements three interfaces from SmartData.Server/Providers/: IDatabaseProvider (connection + lifecycle), ISchemaProvider (read schema), IRawDataProvider (raw reads/writes). Registration is a single service call — swap SQLite for SQL Server without touching procedures or entities. Multi-database is first-class: the Database arg on each RPC selects which logical database the call targets.
See: Providers.
Built-in subsystems
| Subsystem | What it does | Read more |
|---|---|---|
| Scheduler | Schedule attributes on a procedure ([Daily], [Every], [Weekly], [Monthly], [MonthlyDow], [Once]). Code owns when; users own only Enabled, retry, and jitter. Multi-instance safe via unique-index claim + heartbeat. |
Scheduling |
| Tracking & Ledger | Opt-in [Tracked] provisions {Table}_History (post-image + op/user/timestamp). [Ledger] adds a SHA-256 hash chain for tamper-evident audit. |
Tracking |
| Session / Auth | PBKDF2 password hashing, token-scoped sessions, RBAC permissions. | smartdata-server |
| Metrics | Counters, histograms, and spans collected per-procedure. | smartdata-server |
| Backup | Versioned manifest-based backup/restore. | smartdata-server |
| Admin UI | Razor/MVC + HTMX + Tailwind. Tables, query builder, users, schedules, metrics, backups. | smartdata-console |
| CLI | sd single-file executable; config persisted at ~/.sd/config.json. |
smartdata-cli |
Where to go next
- Build something — Install → First procedure → First RPC call
- Mental models — Procedures · Database context · Binary RPC
- API surface — System procedures · SmartData.Server reference