Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works
Anything · Lazarus or Delphi
Random projectRandom project

Trysil

A lightweight, attribute-driven ORM for Delphi

View on GitHub

Member rating

No ratings yet.

Sign in to rate this project.

README

Trysil - Delphi ORM

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> 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 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 kid key rotation), multi-tenant support
  • OpenAPI 3.1 document - Trysil.OpenAPI describes 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

pascal
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

pascal
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

Trysil - Delphi ORM from scratch

▶ Watch: Trysil — Delphi ORM from scratch

4. Filter with the fluent builder

pascal
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

pascal
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. For the OpenAPI document add modules\Trysil\Trysil.OpenAPI.

Manual

  1. Clone the repository

    pascal
    git clone https://github.com/davidlastrucci/Trysil.git
  2. Open Packages/<ver>/TrysilGroup.groupproj in the Delphi IDE and Build All, or run from the command line:

    pascal
    Packages\Build370.bat
  3. Add the output path to your project's Search Path:

    pascal
    $(Trysil)\$(Platform)\$(Config)

    where $(Trysil) points to Lib/<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

pascal
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 server

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