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.gitvar 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.
| Dapper | Massive | EF Core | MicroORM | |
|---|---|---|---|---|
| Raw SQL, mapped to objects | ||||
| SQL injection blocked by the type system | — | — | FromSql | every API |
| Typed LINQ-style queries | — | — | a focused subset | |
| Unsupported query throws, no client eval | n/a | n/a | ||
| CRUD without writing SQL | — | |||
| Composite keys and optimistic concurrency | — | — | ||
| Atomic upsert | — | — | — | |
| Multi-mapping joins, multiple result sets | — | — | ||
| Stored procedures with outputs | raw SQL | |||
| Change tracking, migrations | — | — | by design, no | |
| Dependencies | none | none | many | none |
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