// CSharpDB — Embedded Database Engine for .NET
// Zero dependencies. ACID-compliant. Production-grade.

using CSharpDB.Engine;
using CSharpDB.Data;
using System.Threading.Channels;

namespace MyApp.DataLayer;

public sealed class AppDatabase : IAsyncDisposable
{
    private readonly Database _db;
    private readonly Channel<WriteOp> _writes;

    public static async Task<AppDatabase> OpenAsync(string path)
    {
        var db = await Database.OpenAsync(path);
        return new AppDatabase(db);
    }

    private AppDatabase(Database db)
    {
        _db = db;
        _writes = Channel.CreateBounded<WriteOp>(1024);
    }

    public async Task CreateSchemaAsync()
    {
        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 Products (
                Id       INTEGER PRIMARY KEY,
                Name     TEXT NOT NULL,
                Price    REAL NOT NULL,
                Category TEXT,
                Created  TEXT DEFAULT CURRENT_TIMESTAMP
            );

            CREATE INDEX IF NOT EXISTS idx_products_category
                ON Products(Category);

            CREATE TABLE IF NOT EXISTS Orders (
                Id         INTEGER PRIMARY KEY,
                ProductId  INTEGER REFERENCES Products(Id),
                Quantity   INTEGER NOT NULL,
                Total      REAL NOT NULL,
                OrderDate  TEXT DEFAULT CURRENT_TIMESTAMP
            );";
        await cmd.ExecuteNonQueryAsync();
    }

    public async Task<IReadOnlyList<Product>> GetTopProductsAsync(int limit)
    {
        await using var conn = new CSharpDbConnection("Data Source=myapp.db");
        await conn.OpenAsync();

        await using var cmd = conn.CreateCommand();
        cmd.CommandText = @"
            SELECT p.Id, p.Name, p.Price, SUM(o.Quantity) AS TotalSold
            FROM Products p
            JOIN Orders o ON o.ProductId = p.Id
            GROUP BY p.Id, p.Name, p.Price
            ORDER BY TotalSold DESC
            LIMIT @limit";
        cmd.Parameters.Add(new CSharpDbParameter("@limit", limit));

        var results = new List<Product>();
        await using var reader = await cmd.ExecuteReaderAsync();
        while (await reader.ReadAsync())
        {
            results.Add(new Product(
                reader.GetInt32(0),
                reader.GetString(1),
                reader.GetDouble(2),
                reader.GetInt32(3)
            ));
        }
        return results;
    }

    // Collection API for flexible document storage
    public async Task StoreSessionAsync(UserSession session)
    {
        var sessions = await _db.GetCollectionAsync<UserSession>("sessions");
        await sessions.PutAsync(session.Id, session);
    }

    public async Task<UserSession?> GetSessionAsync(string id)
    {
        var sessions = await _db.GetCollectionAsync<UserSession>("sessions");
        return await sessions.GetAsync(id);
    }

    public async ValueTask DisposeAsync()
    {
        _writes.Writer.Complete();
        await _db.DisposeAsync();
    }
}

public record Product(int Id, string Name, double Price, int TotalSold);
public record UserSession(string Id, string UserId, DateTime Expires);

// Query with the Engine API
await using var result = await db.ExecuteAsync(
    "SELECT Name, Price FROM Products ORDER BY Price DESC LIMIT 5");
while (await result.MoveNextAsync())
    Console.WriteLine($"{result.Current[0].AsText}: ${result.Current[1].AsReal}");

// ─── End of sample ───

// CSharpDB — Embedded Database Engine for .NET
// Zero dependencies. ACID-compliant. Production-grade.

using CSharpDB.Engine;
using CSharpDB.Data;
using System.Threading.Channels;

namespace MyApp.DataLayer;

public sealed class AppDatabase : IAsyncDisposable
{
    private readonly Database _db;
    private readonly Channel<WriteOp> _writes;

    public static async Task<AppDatabase> OpenAsync(string path)
    {
        var db = await Database.OpenAsync(path);
        return new AppDatabase(db);
    }

    private AppDatabase(Database db)
    {
        _db = db;
        _writes = Channel.CreateBounded<WriteOp>(1024);
    }

    public async Task CreateSchemaAsync()
    {
        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 Products (
                Id       INTEGER PRIMARY KEY,
                Name     TEXT NOT NULL,
                Price    REAL NOT NULL,
                Category TEXT,
                Created  TEXT DEFAULT CURRENT_TIMESTAMP
            );

            CREATE INDEX IF NOT EXISTS idx_products_category
                ON Products(Category);

            CREATE TABLE IF NOT EXISTS Orders (
                Id         INTEGER PRIMARY KEY,
                ProductId  INTEGER REFERENCES Products(Id),
                Quantity   INTEGER NOT NULL,
                Total      REAL NOT NULL,
                OrderDate  TEXT DEFAULT CURRENT_TIMESTAMP
            );";
        await cmd.ExecuteNonQueryAsync();
    }

    public async Task<IReadOnlyList<Product>> GetTopProductsAsync(int limit)
    {
        await using var conn = new CSharpDbConnection("Data Source=myapp.db");
        await conn.OpenAsync();

        await using var cmd = conn.CreateCommand();
        cmd.CommandText = @"
            SELECT p.Id, p.Name, p.Price, SUM(o.Quantity) AS TotalSold
            FROM Products p
            JOIN Orders o ON o.ProductId = p.Id
            GROUP BY p.Id, p.Name, p.Price
            ORDER BY TotalSold DESC
            LIMIT @limit";
        cmd.Parameters.Add(new CSharpDbParameter("@limit", limit));

        var results = new List<Product>();
        await using var reader = await cmd.ExecuteReaderAsync();
        while (await reader.ReadAsync())
        {
            results.Add(new Product(
                reader.GetInt32(0),
                reader.GetString(1),
                reader.GetDouble(2),
                reader.GetInt32(3)
            ));
        }
        return results;
    }
}
Open Source Database Engine

The Embedded Database
Built for .NET

Zero dependencies. Full 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.

Full SQL Engine

DDL, DML, JOINs, aggregates, CTEs, subqueries, views, triggers, and stored procedures.

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

db = ctypes.CDLL("./libcsharpdb.so")

db.csharpdb_open(b"app.db")
db.csharpdb_exec(b"INSERT INTO Users VALUES (1, 'Alice')")
result = db.csharpdb_query(b"SELECT * FROM Users")
db.csharpdb_close()
Rust
extern "C" {
    fn csharpdb_open(path: *const c_char);
    fn csharpdb_exec(sql: *const c_char);
    fn csharpdb_query(sql: *const c_char) -> *const c_char;
    fn csharpdb_close();
}

unsafe {
    csharpdb_open(c"app.db".as_ptr());
    csharpdb_exec(c"SELECT * FROM Users".as_ptr());
    csharpdb_close();
}
Go
// #cgo LDFLAGS: -L. -lcsharpdb
// #include "csharpdb.h"
import "C"

func main() {
    C.csharpdb_open(C.CString("app.db"))
    C.csharpdb_exec(C.CString("SELECT * FROM Users"))
    C.csharpdb_close()
}
Node.js
const ffi = require('ffi-napi');

const db = ffi.Library('./libcsharpdb', {
    'csharpdb_open':  ['void', ['string']],
    'csharpdb_exec':  ['void', ['string']],
    'csharpdb_query': ['string', ['string']],
    'csharpdb_close': ['void', []],
});

db.csharpdb_open("app.db");
db.csharpdb_exec("SELECT * FROM Users");
db.csharpdb_close();

Built with dotnet publish -r linux-x64 /p:NativeLib=Shared — produces a standard .so / .dll / .dylib with no runtime required.

Built for .NET

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

NativeAOT Ready

Ahead-of-time compile your app and CSharpDB together. Sub-millisecond cold starts with no JIT overhead.

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.

No Reflection

Serialization uses source generators and compile-time analysis. Trimmer-safe, AOT-friendly, fully transparent.

How CSharpDB Compares

A fair look at where CSharpDB fits alongside other embedded options.

Feature CSharpDB SQLite LiteDB RocksDB
Pure .NET / No native binaries
Full SQL (JOINs, CTEs, subqueries)
NoSQL Collection API
ACID transactions
Built-in ETL pipelines
Full-text search
REST API / gRPC
Admin UI
MCP server (AI agents)
Mature ecosystem / battle-tested
Collation & Unicode sorting
Multi-language SDKs (Python, Java, …)

Ready to get started?

Add CSharpDB to your .NET project in seconds.

Get Started