A lightweight, attribute-driven ORM for Delphi
Map database tables to classes. Query, insert, update, delete — all through clean Object Pascal.
- Attribute-based mapping — decorate classes with
[TTable],[TColumn],[TPrimaryKey]and you're done - 7 database drivers — Firebird, InterBase, MariaDB, Oracle, PostgreSQL, SQL Server, SQLite — all through FireDAC
- Fluent query builder — type-safe filtering with
TTFilterBuilder<T> - Lazy loading —
TTLazy<T>andTTLazyList<T>for related entities - Change tracking & soft delete —
[TCreatedAt],[TUpdatedAt],[TDeletedAt]with automatic timestamps and user tracking - Optimistic locking — built-in via
[TVersionColumn] - Identity map — per-context, multi-tenant safe
- Unit of Work —
TTSession<T>applies the inserts, updates and deletes you mark in one transaction - JSON serialization — full round-trip with
TTJSonContext - REST HTTP module — attribute-based routing, CORS, JWT (HS256 and RS256, with
kidkey rotation), multi-tenant support - Nullable types —
TTNullable<T>generic wrapper - Connection pooling — delegated to FireDAC
- Structured logging — SQL tracing with thread-safe correlation IDs
- IDE Expert — visual entity designer, model & DDL generators, REST scaffolder, and one-click install of AI assistant skills (Claude Code, Cursor, Copilot, Windsurf)
type
[TTable('Persons')]
[TSequence('PersonsID')]
TPerson = class
strict private
[TPrimaryKey]
[TColumn('ID')]
FID: TTPrimaryKey;
[TColumn('Firstname')]
FFirstname: String;
[TColumn('Lastname')]
FLastname: String;
[TVersionColumn]
[TColumn('VersionID')]
FVersionID: TTVersion;
public
property ID: TTPrimaryKey read FID;
property Firstname: String read FFirstname write FFirstname;
property Lastname: String read FLastname write FLastname;
end;var
LContext: TTContext;
LPersons: TTList<TPerson>;
LPerson: TPerson;
begin
LContext := TTContext.Create(LConnection);
try
// Read all
LPersons := LContext.CreateEntityList<TPerson>();
try
LContext.SelectAll<TPerson>(LPersons);
for LPerson in LPersons do
Writeln(Format('%s %s', [LPerson.Firstname, LPerson.Lastname]));
finally
LPersons.Free;
end;
// Insert
LPerson := LContext.CreateEntity<TPerson>();
try
LPerson.Firstname := 'David';
LPerson.Lastname := 'Lastrucci';
LContext.Insert<TPerson>(LPerson);
finally
LContext.FreeEntity<TPerson>(LPerson);
end;
finally
LContext.Free;
end;
end;

▶ Watch: Trysil — Delphi ORM from scratch
var
LFilter: TTFilter;
begin
LFilter := LContext.CreateFilterBuilder<TPerson>()
.Where('Lastname').Equal('Lastrucci')
.OrderByAsc('Firstname')
.Limit(10)
.Build;
LContext.Select<TPerson>(LPersons, LFilter);
end;| Database | Driver unit | Notes |
|---|---|---|
| Firebird | Trysil.Data.FireDAC.FirebirdSQL |
Localhost/embedded on Community; remote server requires Enterprise |
| InterBase | Trysil.Data.FireDAC.InterBase |
Community edition; generator-based sequences |
| MariaDB | Trysil.Data.FireDAC.MariaDB |
MariaDB 10.3+ (native sequences), via the FireDAC MySQL driver; localhost on Community, remote requires Enterprise |
| Oracle | Trysil.Data.FireDAC.Oracle |
Requires Enterprise edition; EZConnect descriptor //host:port/service |
| PostgreSQL | Trysil.Data.FireDAC.PostgreSQL |
Localhost on Community; remote server requires Enterprise |
| SQL Server | Trysil.Data.FireDAC.SqlServer |
Requires Enterprise edition |
| SQLite | Trysil.Data.FireDAC.SQLite |
Community edition; great for development and testing |
FireDAC driver availability follows the RAD Studio edition matrix: Professional/Community covers local/embedded access (SQLite, InterBase, and localhost-only PostgreSQL/MySQL-MariaDB/Firebird), while full client/server connectivity — and SQL Server and Oracle in any form — requires Enterprise/Architect.
| Version | Codename |
|---|---|
| Delphi 10.3 | Rio |
| Delphi 10.4 | Sydney |
| Delphi 11 | Alexandria |
| Delphi 12 | Athens |
| Delphi 13 | Florence (active development) |
All packages build on Community Edition, except Trysil.SqlServer and Trysil.Oracle, which require Enterprise/Architect (their FireDAC driver units ship only with those editions).
Install directly from the Delphi IDE: Tools > GetIt Package Manager, search for Trysil.
Or visit: getitnow.embarcadero.com/trysil-delphi-orm
boss install davidlastrucci/Trysil
Boss adds the core sources to the Search Path, subfolders included. For the JSON
and HTTP modules add modules\Trysil\Trysil.JSon and modules\Trysil\Trysil.Http
as well, together with the three subfolders of the latter: Authentication,
Log and MultiTenant.
- Clone the repository
git clone https://github.com/davidlastrucci/Trysil.git - Open
Packages/<ver>/Trysil.groupprojin the Delphi IDE and Build All, or run from the command line:Packages\Build370.bat - Add the output path to your project's Search Path:
where
$(Trysil)\$(Platform)\$(Config)$(Trysil)points toLib/<ver>.
See the full Installation guide for details, including the optional IDE Expert.
| Resource | Link |
|---|---|
| Online Help | davidlastrucci.github.io/Trysil |
| Blog | trysil.lastrucci.net |
TTContext ───────────────────────────── Main API
├── TTProvider SELECT / Read operations
├── TTResolver INSERT / UPDATE / DELETE
│ ├── Validation (attributes)
│ └── Events (Before/After hooks)
├── TTIdentityMap Per-context entity cache
├── TTSession<T> Unit of Work
├── TTTransaction Explicit transaction management
└── TTFilterBuilder<T> Fluent query builder
TTConnection (abstract)
└── TTGenericConnection
├── SQLite
├── PostgreSQL
├── SQL Server
├── Firebird
├── InterBase
├── MariaDB
└── Oracle
Modules
├── Trysil → ORM core
├── Trysil.JSon → JSON serialization via TTJSonContext
└── Trysil.Http → REST hosting, routing, CORS, JWT, multi-tenant
During World War II, ORM was a British operation to establish a reception base centred on Trysil in eastern Norway (source). That's why this ORM is called Trysil.
Projects and applications using Trysil in production. See the full list — and add yours!
If Trysil is useful to you, please consider:
- Star this repository — it's free and helps others discover the project
- Share your project in the Show and tell issue
- Donate via
- Reach out at david.lastrucci@gmail.com — feedback is always welcome
BSD-3-Clause — see LICENSE.md for details.
Trysil takes its name from Operation ORM, a World War II Allied operation.
Made with ❤️ by David Lastrucci