Readme.md

June 11, 2026 · View on GitHub

Trysil - Delphi ORM

A lightweight, attribute-driven ORM for Delphi
Map database tables to classes. Query, insert, update, delete — all through clean Object Pascal.

License GitHub Stars Delphi 10.3 to 13 GetIt Blog


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 loadingTTLazy<T> and TTLazyList<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 WorkTTSession<T> tracks and applies changes automatically
  • JSON serialization — full round-trip with TTJSonContext
  • REST HTTP module — attribute-based routing, CORS, JWT, multi-tenant support
  • Nullable typesTTNullable<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 := TTList<TPerson>.Create;
    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
      LPerson.Free;
    end;
  finally
    LContext.Free;
  end;
end;

3. Watch it in action

Trysil - Delphi ORM from scratch
▶ 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

DatabaseDriver unitNotes
FirebirdTrysil.Data.FireDAC.FirebirdSQLLocalhost/embedded on Community; remote server requires Enterprise
InterBaseTrysil.Data.FireDAC.InterBaseCommunity edition; generator-based sequences
MariaDBTrysil.Data.FireDAC.MariaDBMariaDB 10.3+ (native sequences), via the FireDAC MySQL driver; localhost on Community, remote requires Enterprise
OracleTrysil.Data.FireDAC.OracleRequires Enterprise edition; EZConnect descriptor //host:port/service
PostgreSQLTrysil.Data.FireDAC.PostgreSQLLocalhost on Community; remote server requires Enterprise
SQL ServerTrysil.Data.FireDAC.SqlServerRequires Enterprise edition
SQLiteTrysil.Data.FireDAC.SQLiteCommunity 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

VersionCodename
Delphi 10.3Rio
Delphi 10.4Sydney
Delphi 11Alexandria
Delphi 12Athens
Delphi 13Florence (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

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/Trysil

Manual

  1. Clone the repository
    git clone https://github.com/davidlastrucci/Trysil.git
    
  2. Open Packages/<ver>/Trysil.groupproj in the Delphi IDE and Build All, or run from the command line:
    Packages\Build370.bat
    
  3. Add the output path to your project's Search Path:
    $(Trysil)\$(Platform)\$(Config)
    
    where $(Trysil) points to Lib/<ver>.

See the full Setup guide for details.

Documentation

ResourceLink
Online Helpdavidlastrucci.github.io/Trysil
Blogtrysil.lastrucci.net
Manual (English)PDF
Manual (Italiano)PDF

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

The 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 issue
  • Donate via PayPal
  • 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