---
title: "onelite"
url: https://recursiveai.org/onelite/
description: "An embedded SQL database for .NET in pure C# that reads and writes SQLite files, with no native library: SQL engine, ADO.NET provider, FTS3/4/5, R*Tree, vec0, backup and SQLCipher-4-compatible encryption. Compatibility measured against SQLite 3.53.4. A preview. MIT or Apache-2.0."
---

# onelite

An embedded SQL database for .NET, written in C#, that reads and writes SQLite files, with no native library to ship: trimming, NativeAOT and the browser included.

> **Fixed in 0.2.0-preview.2: upgrade.** From the Known issues section of [the README at v0.2.0-preview.2](https://github.com/recursive-ai-oss/onelite-csharp/blob/v0.2.0-preview.2/README.md#known-issues): “**0.2.0-preview.1 can silently drop a write (data loss); upgrade to 0.2.0-preview.2.** In a rollback-journal mode (`journal_mode` DELETE, TRUNCATE or PERSIST, the default for `Database.Open` and `OneLiteConnection`), an `INSERT`, `UPDATE` or `DELETE` in autocommit mode returned success with no change while another connection held a read, in the same process or another one. It now fails with `SQLITE_BUSY` (‘database is locked’) as SQLite does; WAL mode was never affected. Remaining differences between several connections on one file are listed in [docs/engine.md](https://recursiveai.org/onelite/docs/engine/#known-differences-with-several-connections-on-one-file). “**0.2.0-preview.1 could silently lose a key change; upgrade to 0.2.0-preview.2.** A key change could be silently lost: `PRAGMA rekey` or `PRAGMA hexrekey` run through a call that reads one row and stops (`ExecuteScalar`, a reader closed early, `Statement.Step` once, the happy-path scalar and query methods) answered `ok` but kept the old key. `ExecuteNonQuery` and running the statement to completion were not affected. Upgrade to 0.2.0-preview.2, or after a rekey in preview.1 reopen the file with the new key to confirm it.”

```sh
dotnet add package RecursiveAI.OneLite --prerelease
```

- [Getting started](https://recursiveai.org/onelite/docs/getting-started/)
- [Docs](https://recursiveai.org/onelite/docs/)
- [Cookbook](https://recursiveai.org/onelite/cookbook/)
- [GitHub](https://github.com/recursive-ai-oss/onelite-csharp)
- [NuGet](https://www.nuget.org/packages/RecursiveAI.OneLite)

## A quick look

Open a file, write in a transaction, query with bound parameters. The result is an ordinary SQLite database that the `sqlite3` shell opens and checks clean.

[Getting started](https://recursiveai.org/onelite/docs/getting-started/)

*Program.cs · C#*

```
using RecursiveAI.OneLite;
 
await using var db = await Database.OpenAsync("books.db");
await db.Table<Book>().EnsureCreatedAsync();
 
await db.WriteAsync(async tx =>
    await tx.Table<Book>().InsertAsync(new() { Title = "Dune" }));
 
// {year} is a bound parameter, never pasted into the SQL
var books = await db.QueryAsync<Book>(
    $"select * from books where Year > {year}");
```

### SQLite files, both ways

Database, rollback-journal, WAL and shared-memory files, read and written in the SQLite format. Files `sqlite3` writes open in OneLite, and files OneLite writes open in `sqlite3`.

[Open an existing .db file](https://recursiveai.org/onelite/cookbook/open-existing-sqlite-database-csharp/)

### The SQL engine

Joins, subqueries, recursive CTEs, aggregates, window functions, views, triggers, upsert, `RETURNING`, `STRICT` and `WITHOUT ROWID` tables, `ALTER TABLE`, `ATTACH`, JSON and math functions, transactions and savepoints.

[Transactions in C#](https://recursiveai.org/onelite/cookbook/sqlite-transactions-csharp/)

### No native library

Written in C# on the base class library alone. A publish ships one managed assembly and no `e_sqlite3` binary per platform, and it builds for trimming, NativeAOT and the browser.

[SQLite without native dependencies](https://recursiveai.org/onelite/cookbook/sqlite-csharp-without-native-dependencies/)

### The happy path

`$"…"` queries whose holes are bound parameters, `WriteAsync` transactions with retry, `Table<T>`, source-generated mapping with no reflection, and `MigrateAsync`.

[Create, insert and query](https://recursiveai.org/onelite/cookbook/create-sqlite-database-csharp/)

### ADO.NET with real async

`RecursiveAI.OneLite.Data`: `DbConnection`, `DbCommand`, `DbDataReader`, `DbDataSource` and batches, with async calls that await the storage layer.

[ADO.NET and parameters](https://recursiveai.org/onelite/cookbook/sqlite-ado-net-csharp/)

### Search

FTS5, FTS3 and FTS4 on the documented shadow-table layouts, R*Tree, and `vec0` for exact nearest-neighbour search. `SearchAsync` fuses full-text and vector results.

### Backup and blobs

The backup API, `VACUUM INTO`, incremental blob I/O and `:memory:` databases.

### SQLCipher-4-compatible encryption

Encrypted database, journal and WAL with SQLCipher 4’s format. It has had [the project’s own review](https://recursiveai.org/onelite/docs/encryption-review/) (not an external audit) and has not been independently audited.

### Clearer errors

SQLite’s result codes and messages, unchanged, plus the position in the SQL with a caret, the offending name and suggestions.

## Measured against SQLite 3.53.4

OneLite aims to behave like one pinned SQLite release, the 3.53.4 `sqlite3` shell from sqlite.org: the same query results, result codes and error messages. These are the project’s measurements for 0.2.0-preview.2, quoted from its [compatibility page](https://recursiveai.org/onelite/docs/compatibility/), which lists every known difference.

- **sqllogictest, SQL engine (all groups):** “622 files, 7,420,713 records: 5,939,877 pass, 0 wrong answers, 1 explained failure; 1,480,834 records are written for other database engines and skipped”
- **Differential testing against `sqlite3`:** “4 seeds, 22 minutes each, about 12,000 generated cases and 0.8 M checks: 0 unexplained differences”
- **Files:** files written by `sqlite3` (“every page type, overflow, freelists, auto-vacuum modes, encodings, page sizes, WAL states, hot journals”) read by OneLite: “all identical”; files written by OneLite “pass `sqlite3`’s `PRAGMA integrity_check` and give the same `.dump`”: “all pass”
- **Live beside `sqlite3` in WAL mode:** “10,000 interleaved commits, consistent both ways”
- **FTS:** FTS5, “25-minute run: 19 of 647 cases differ, all in the window `snippet` chooses or a malformed-query quirk of the shell”; FTS3 and FTS4, “25-minute run: 264 cases, 0 differing”
- **Durability:** process kills and injected faults, judged by `sqlite3`: “0 corruptions and 0 lost acknowledged commits in every campaign so far”

Known gaps include the last bit of text-to-REAL conversions with 20 or more significant digits, the order of ties inside a window, and row order before a runtime error when plans differ. In the page’s words, “Native extensions (`load_extension`) are not supported” and “Geopoly, sessions and changesets, `carray` and the shell’s miscellaneous extensions are not implemented.” “`PRAGMA optimize` and `PRAGMA incremental_vacuum` are accepted and do nothing: no statistics are gathered and no free pages are returned. Use `ANALYZE` and a full `VACUUM` instead.”

[The full compatibility page](https://recursiveai.org/onelite/docs/compatibility/)

## Status and packages

- **Status**: From the README: “Preview (`0.2.0-preview.2`). The storage layer, the SQL engine, `RecursiveAI.OneLite.Data` and the happy-path API work, as do FTS3/4/5, R*Tree, `vec0` (OneLite’s own vector table: it follows sqlite-vec’s SQL API but its files are not interchangeable with sqlite-vec’s, see [docs/vec.md](https://recursiveai.org/onelite/docs/vec/)), the backup API and SQLCipher-4-compatible encryption. Measured compatibility with SQLite 3.53.4, including every known difference, is in [docs/compatibility.md](https://recursiveai.org/onelite/docs/compatibility/).”
- **Several connections**: From the README: “Remaining differences between several connections on one file are listed in [docs/engine.md](https://recursiveai.org/onelite/docs/engine/#known-differences-with-several-connections-on-one-file).”
- **How it is built**: From [the README](https://github.com/recursive-ai-oss/onelite-csharp/blob/v0.2.0-preview.2/README.md#how-it-is-built): “OneLite is a clean-room implementation. … No source code of SQLite, SQLCipher or other SQLite implementations was read, ported or translated.”
- **vec0**: OneLite’s own vector table, not sqlite-vec. From [docs/vec.md](https://recursiveai.org/onelite/docs/vec/): “A `vec0` table written by OneLite can’t be used by sqlite-vec, and one written by sqlite-vec can’t be used by OneLite.”
- **OneLite**: `RecursiveAI.OneLite`: the storage layer, the SQL engine and the happy-path API, with no dependency beyond .NET. Preview, 0.2.0-preview.2.
- **Data**: `RecursiveAI.OneLite.Data`: the ADO.NET provider; depends on the core only. Preview, 0.2.0-preview.2.
- **Not yet**: From the README: “Still to come before 1.0: `BEGIN CONCURRENT`, the `Microsoft.Data.Sqlite`/EF Core adapter, the `onelite` command-line tool, and published benchmarks. APIs may change between previews.”
- **.NET**: .NET 10, C#, checked against the `sqlite3` shell. MIT or Apache-2.0.

## Go further

- [GitHub](https://github.com/recursive-ai-oss/onelite-csharp)
- [NuGet](https://www.nuget.org/packages/RecursiveAI.OneLite)
- [NuGet: OneLite.Data](https://www.nuget.org/packages/RecursiveAI.OneLite.Data)
- [Getting started](https://recursiveai.org/onelite/docs/getting-started/)
- [All docs](https://recursiveai.org/onelite/docs/)
- [Cookbook](https://recursiveai.org/onelite/cookbook/)
- [Compatibility](https://recursiveai.org/onelite/docs/compatibility/)
- [Changelog](https://recursiveai.org/onelite/docs/changelog/)

OneLite is not affiliated with or endorsed by the SQLite developers; “SQLite” is a registered trademark of Hipp, Wyrick & Company.
