MicroORM
.NET 10 · SQLite, PostgreSQL, SQL Server, MySQL

SQL in, objects out.

MicroORM is a small, provider-agnostic ORM for .NET. Write SQL where SQL is the best tool, typed queries where they're clearer, and every value you pass is a parameter.

$git clone https://github.com/HilthonTT/MicroORM.git
Program.cs
var db = new MicroDb(SqlDialect.PostgreSql, dataSource);

// Every {hole} becomes a parameter. Plain strings don't compile.
var recent = await db.QueryAsync<Order>(
    $"SELECT * FROM orders WHERE placed_at > {since} AND status IN {statuses}");

// Typed queries translated to SQL, never silently run in memory.
var vips = await db.Table<Customer>()
    .Where(c => c.Active && c.LifetimeSpend > 10_000)
    .OrderByDescending(c => c.LifetimeSpend)
    .Take(20)
    .ToListAsync();

A quick tour

Less ceremony than a full ORM, more help than raw ADO.NET.

Map rows to plain classes by convention, query them with lambdas or interpolated SQL, and write them back with one call. No context, no change tracker, no migrations.

CRUD without SQL

var books = db.Table<Book>();
await books.InsertAsync(book);      // book.Id is now set
book.Finished = true;
await books.UpdateAsync(book);
var found = await books.FindAsync(book.Id);
await books.UpsertAsync(book, on: b => b.Isbn);

Set-based writes

await db.Table<Customer>()
    .Where(c => c.LastSeen < cutoff)
    .ExecuteUpdateAsync(s => s.Set(c => c.Active, false));

await db.Table<Session>()
    .Where(s => s.ExpiresAt < now)
    .ExecuteDeleteAsync();

Projections and aggregates

var names = await db.Table<Customer>()
    .Where(c => c.Active)
    .Select(c => new { c.Id, c.Name })
    .ToListAsync();

var revenue = await db.Table<Order>()
    .Where(o => o.Paid)
    .SumAsync(o => o.Total);

Joins into objects

var rows = await db.QueryAsync<Order, Customer, (Order, Customer?)>(
    $"""
    SELECT o.id, o.total, c.id, c.name
    FROM orders o LEFT JOIN customers c ON c.id = o.customer_id
    """,
    (o, c) => (o, c));

Features

Everything you reach for daily, nothing you don't.

Injection-safe by type

Query methods take Sql, an interpolated string handler. Values become parameters; concatenated strings don't compile.

Composable fragments

Build WHERE clauses from pieces, expand collections to IN lists, and quote identifiers with Sql.Identifier.

Honest translation

A small, documented LINQ subset. Anything else throws and points you to .Where($"...") instead of running in memory.

One session model

MicroDb opens a pooled connection per call; MicroTransaction has the same API on one connection.

Optimistic concurrency

Mark a version column and updates or deletes of stale rows throw MicroConcurrencyException.

Atomic upserts

Insert or update in one statement, matched on the key or on any unique columns, on every database.

Type handlers

Value objects, strongly typed IDs, JSON columns and enums as text, in both directions.

Sync and async

Every API has both forms, written once. Reads keep pace with Dapper in time and memory.

Compared

Between a micro-ORM and a full ORM.

MicroORM takes ideas from the libraries it learned from and adds a few of its own. It shares no code with any of them.

DapperMassiveEF CoreMicroORM
Raw SQL, mapped to objects
SQL injection blocked by the type system——FromSqlevery API
Typed LINQ-style queries——a focused subset
Unsupported query throws, no client evaln/an/a
CRUD without writing SQL—
Composite keys and optimistic concurrency——
Atomic upsert———
Multi-mapping joins, multiple result sets——
Stored procedures with outputsraw SQL
Change tracking, migrations——by design, no
Dependenciesnonenonemanynone

Databases

Bring your provider. MicroORM brings the dialect.

The library references no database driver. Pick an ADO.NET provider, pass a SqlDialect, and the integration suite runs against every database in CI.

SQLite

SqlDialect.Sqlite

Microsoft.Data.Sqlite

PostgreSQL

SqlDialect.PostgreSql

Npgsql · PostgreSQL 17

SQL Server

SqlDialect.SqlServer

Microsoft.Data.SqlClient · 2022

MySQL

SqlDialect.MySql

MySqlConnector · MySQL 8.4

From zero to first query in five minutes.

Reference the project, pick a provider, and map your first table.

Read the guide