Open Source Database Engine

The Embedded Database
Built for .NET

Zero dependencies. CSharpDB SQL. ACID storage. One NuGet package gives you everything from query parsing to page-level I/O.

dotnet add package CSharpDB

Ship in 30 Seconds

Use SQL, the Collection API, or low-level storage — all powered by one engine.

Program.cs
using CSharpDB.Data;

await using var conn = new CSharpDbConnection("Data Source=myapp.db");
await conn.OpenAsync();

await using var cmd = conn.CreateCommand();
cmd.CommandText = @"
    CREATE TABLE IF NOT EXISTS Users (
        Id   INTEGER PRIMARY KEY,
        Name TEXT NOT NULL,
        Email TEXT
    )";
await cmd.ExecuteNonQueryAsync();

cmd.CommandText = "INSERT INTO Users VALUES (@id, @name, @email)";
cmd.Parameters.Add(new CSharpDbParameter("@id", 1));
cmd.Parameters.Add(new CSharpDbParameter("@name", "Alice"));
cmd.Parameters.Add(new CSharpDbParameter("@email", "alice@example.com"));
await cmd.ExecuteNonQueryAsync();
Program.cs
using CSharpDB.Engine;

await using var db = await Database.OpenAsync("myapp.db");
var users = await db.GetCollectionAsync<User>("users");

// Put and get by string key
await users.PutAsync("alice", new User("Alice", "alice@example.com", 30));
var alice = await users.GetAsync("alice");

// Create an index and query through it
await users.EnsureIndexAsync(u => u.Email);
await foreach (var match in users.FindByIndexAsync(
    u => u.Email, "alice@example.com"))
    Console.WriteLine(match.Value.Name);

public record User(string Name, string Email, int Age);
Program.cs
using System.Text;
using CSharpDB.Storage.BTrees;
using CSharpDB.Storage.StorageEngine;

var storageOptions = new StorageEngineOptionsBuilder()
    .UseBTreeIndexes()
    .Build();

var factory = new DefaultStorageEngineFactory();
var context = await factory.OpenAsync("lowlevel.cdb", storageOptions);
await using var pager = context.Pager;

await pager.BeginTransactionAsync();
try
{
    uint rootPageId = await BTree.CreateNewAsync(pager);
    var tree = new BTree(pager, rootPageId);

    await tree.InsertAsync(42, Encoding.UTF8.GetBytes("session payload"));
    byte[]? payload = await tree.FindAsync(42);

    if (payload is not null)
        Console.WriteLine(Encoding.UTF8.GetString(payload));

    var cursor = tree.CreateCursor();
    while (await cursor.MoveNextAsync())
        Console.WriteLine($"{cursor.CurrentKey} = {cursor.CurrentValue.Length} bytes");

    await tree.DeleteAsync(42);
    await pager.CommitAsync();
}
catch
{
    await pager.RollbackAsync();
    throw;
}

Zero Dependencies

Pure .NET from page management to query execution. No native binaries, no external packages.

ACID Transactions

WAL-based recovery with snapshot isolation. Concurrent readers never block writers.

CSharpDB SQL Engine

A documented SQL subset with DDL, DML, JOINs, aggregates, CTEs, subqueries, views, triggers, and stored procedures. Read the SQL reference.

Collection API

Typed Collection<T> with JSON serialization, nested path indexing, and range queries.

B+Tree Storage

On-disk key-value storage with automatic node splitting, cursor iteration, and range scans.

ETL Pipelines

Built-in pipeline runtime with CSV/JSON sources, transforms, and destinations.

Every Tool You Need

One engine, many interfaces. Pick the access layer that fits your architecture.

CLI REPL

Interactive SQL shell with autocomplete and result formatting

Admin UI

Browser-based dashboard for browsing, querying, and managing data

REST API

HTTP endpoints for SQL execution, collections, and database management

gRPC Daemon

High-performance binary protocol for remote database access

MCP Server

Model Context Protocol server for AI agent database access

VS Code Extension

Browse databases, run queries, and inspect schemas from your editor

ADO.NET Provider

Standard DbConnection/DbCommand for ORM and data library compatibility

Native FFI

C-compatible shared library for Python, JavaScript, and other languages

Use from Any Language

Compile to a native shared library with NativeAOT. Call CSharpDB from Python, Rust, Go, Node.js, or anything that speaks C.

Python
from csharpdb import CSharpDB

with CSharpDB() as db:
    db.open("app.db")
    print(db.query("SELECT 1 AS value"))

Requires the native library and the wrapper from the Python setup tutorial. Run from the folder containing the library, or pass its path to the wrapper.

Node.js
import { CSharpDB } from './csharpdb.mjs';

const db = new CSharpDB();
try {
    db.open('app.db');
    console.log(db.query('SELECT 1 AS value'));
} finally {
    db.close();
}

Requires the native library and the wrapper from the Node.js setup tutorial. Run from the folder containing the library, or pass its path to the wrapper.

Rust via the C ABI

Use the native header to define your bindings. csharpdb_open(path) returns a database handle; pass it to csharpdb_execute(db, sql) and csharpdb_close(db). Check failed calls with csharpdb_last_error() and free each result with csharpdb_result_free(result).

Read the C ABI header and build the native library. Rust bindings and linker configuration are supplied by your application.

Go via the C ABI

Use the native header to define your bindings. csharpdb_open(path) returns a database handle; pass it to csharpdb_execute(db, sql) and csharpdb_close(db). Check failed calls with csharpdb_last_error() and free each result with csharpdb_result_free(result).

Read the C ABI header and build the native library. Go bindings and linker configuration are supplied by your application.

Build the native project explicitly, for example: dotnet publish src/CSharpDB.Native/CSharpDB.Native.csproj -c Release -r linux-x64. The output is CSharpDB.Native.so on Linux, CSharpDB.Native.dll on Windows, or CSharpDB.Native.dylib on macOS. See the platform prerequisites.

Built for .NET

Not a port. Not a wrapper. Native .NET from the ground up.

NativeAOT Ready

The native shared library is published with NativeAOT. For embedded applications, use the SQL API or registered generated collection models and review the trimming requirements for your chosen API.

Zero-Alloc Hot Paths

Critical read paths use Span<T> and stack allocation. No GC pressure where it matters most.

IAsyncDisposable

First-class await using support everywhere. Clean resource lifetime management with no surprises.

System.Threading.Channels

Internal write batching uses bounded channels for backpressure-aware, lock-free coordination.

Generated Collection Models

The regular GetCollectionAsync<T> API uses reflection-based serialization and member binding. Use GetGeneratedCollectionAsync<T> with a registered model for the trim-safe generated path. See collection API requirements.

How CSharpDB Compares

Compare the engine model and access APIs that fit your application.

Engine and API overview. Documentation reviewed September 7, 2026; capabilities depend on version and configuration.
AreaCSharpDBSQLiteLiteDB v5RocksDB
Data modelSQL tables and typed collectionsSQL tablesDocument collectionsOrdered key-value pairs
Application accessEngine API, Collections, ADO.NET and EF CoreC API and language bindings.NET collection API and object mappingKey-value API and language bindings
Related dataSQL JOINs and subqueriesSQL JOINs and subqueriesEmbedded documents and document referencesApplication-defined keys and values
String orderingCollation supportCollating functionsCulture and comparison optionsConfigurable key comparator
DocumentationSQL support · ToolsSQLite featuresLiteDB overviewRocksDB overview

CSharpDB includes separate Admin, CLI, REST, gRPC, and MCP tools. Other databases have their own tooling and integrations; this overview does not rate the completeness of those ecosystems. For measured CSharpDB workloads and storage-mode tradeoffs, see the performance guide.

Ready to get started?

Add CSharpDB to your .NET project in seconds.

Get Started