Trysil
A lightweight, attribute-driven ORM for Delphi
- Active · last change 11-1-2026
- ★ 160 on GitHub
README

A lightweight, attribute-driven ORM for Delphi
Map database tables to classes. Query, insert, update, delete — all through clean Object Pascal.
Features
- 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 - OpenAPI 3.1 document -
Trysil.OpenAPIdescribes the HTTP server, entity schemas and validation constraints included, on/openapi.json - 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)
Quick Start
1. Define an entity
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;2. Use it
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;3. Watch it in action
▶ Watch: Trysil — Delphi ORM from scratch
4. Filter with the fluent builder
var
LFilter: TTFilter;
begin
LFilter := LContext.CreateFilterBuilder<TPerson>()
.Where('Lastname').Equal('Lastrucci')
.OrderByAsc('Firstname')
.Limit(10)
.Build;
LContext.Select<TPerson>(LPersons, LFilter);
end;Database Support
| 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.
Delphi Compatibility
| 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).
Installation
Via the setup program (recommended)
Download Trysil.Setup.exe and run it with Delphi closed. It finds the Delphi versions installed, downloads the latest release from GitHub, builds the packages and the IDE Expert, and sets the Trysil variable and the library path of each IDE. On an edition that cannot build from the command line it points the library path at the sources. It runs as the user, writes only under HKEY_CURRENT_USER, and is registered in the installed apps of Windows, from where it updates and uninstalls Trysil. The setup guide walks through each page and what the setup changes.
The setup is not signed: the first time, Windows SmartScreen shows Windows protected your PC. Click More info, then Run anyway. The source of the setup is in Trysil.Setup.
Via GetIt
Install directly from the Delphi IDE: Tools > GetIt Package Manager, search for Trysil.
Or visit: getitnow.embarcadero.com/trysil-delphi-orm
Via Boss
boss install davidlastrucci/TrysilBoss 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. For the OpenAPI document add modules\Trysil\Trysil.OpenAPI.
Manual
-
Clone the repository
git clone https://github.com/davidlastrucci/Trysil.git -
Open
Packages/<ver>/TrysilGroup.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:
$(Trysil)\$(Platform)\$(Config)where
$(Trysil)points toLib/<ver>.
See the full Installation guide for details, including the optional IDE Expert.
Documentation
| Resource | Link |
|---|---|
| Online Help | davidlastrucci.github.io/Trysil |
| Blog | trysil.lastrucci.net |
Architecture Overview
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
????????? Trysil.OpenAPI ??? OpenAPI 3.1 document of the HTTP serverThe Name
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.
Built With Trysil
Projects and applications using Trysil in production. See the full list — and add yours!
Support the Project
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 discussion
- Donate via
- Reach out at david.lastrucci@gmail.com — feedback is always welcome
License
BSD-3-Clause — see LICENSE.md for details.
Naming
Trysil takes its name from Operation ORM, a World War II Allied operation.
Made with ❤️ by David Lastrucci


