Skip to content

Repository files navigation

CSharpDB

CSharpDB

The embedded database engine built for .NET
Zero dependencies. CSharpDB SQL. ACID storage. Single file. One NuGet package.

NuGet NuGet downloads CI GitHub stars .NET 10 Platform: Windows, Linux, macOS License: MIT Release

Getting Started · Docs · Benchmarks · Roadmap · Website


Performance at a Glance

1.99M gets/sec 9.68M COUNTs/sec 799.29K rows/sec 890 commits/sec
Collection point reads Concurrent reader burst (8x reused) Durable InsertBatch B10000 Concurrent durable writes

Intel i9-11900K, 16 logical cores, Windows 10.0.26300, .NET SDK 10.0.203, .NET runtime 10.0.7. Snapshot promoted from the May 6, 2026 release-core suite; latest release guardrail compare passed May 6, 2026 with PASS=187, WARN=0, SKIP=0, FAIL=0. Full results live in the benchmark suite.


Durable API Top Lines

Default CSharpDB file-backed benchmarks are fully durable: WAL fsync-on-commit unless a row explicitly says otherwise. In-memory rows show the same API paths without disk durability.

Surface Single write Batch x100 Point read Concurrent read
SQL file-backed 267.1 ops/sec 25.56K rows/sec 1.48M ops/sec 9.68M COUNTs/sec
SQL hybrid incremental-durable 276.1 ops/sec 26.55K rows/sec 1.47M ops/sec 10.04M COUNTs/sec
SQL in-memory 259.48K ops/sec 934.22K rows/sec 1.49M ops/sec 10.26M COUNTs/sec
Collection file-backed 265.7 ops/sec 24.53K docs/sec 1.99M ops/sec -
Collection hybrid incremental-durable 276.9 ops/sec 25.75K docs/sec 2.02M ops/sec -
Collection in-memory 262.14K ops/sec 969.55K docs/sec 2.02M ops/sec -

Source: master-table-20260506-024609-median-of-3.csv from the May 6, 2026 release-core snapshot. Full methodology and storage-mode detail live in the benchmark suite README.


Concurrent Durable Writes

The current release-core concurrent write rows measure the intended shared-insert shape: one shared Database, disjoint explicit key ranges, auto-commit SQL inserts, and ConcurrentWriteTransactions enabled. The numbers below are total durable commits/sec across all writers combined.

Workload Writers Commit window Durable Commits/sec Commits/flush Notes
Shared auto-commit INSERT 4 0 247.0 1.00 One durable flush per commit
Shared auto-commit INSERT 4 250us 463.4 1.99 Group commit roughly doubles throughput
Shared auto-commit INSERT 8 0 239.2 1.00 Still flush-bound with no commit window
Shared auto-commit INSERT 8 250us 890.1 3.94 Current release-core headline row

Focused hot insert fan-in diagnostics cover the newer right-edge and auto-ID shapes that are not part of the release-core scorecard yet:

Insert shape Writers/window Durable Commits/sec Commits/flush
Serialized explicit hot right-edge W8 + 250us 278.4 1.00
Concurrent explicit hot right-edge W8 + 250us 910.3 3.33
Concurrent auto-ID hot right-edge W8 + 250us 913.1 3.34
Concurrent explicit disjoint ranges W8 + 250us 1,049.6 3.96

Sources: release-core concurrent-write-diagnostics-20260506-032735-median-of-3.csv; focused insert fan-in diagnostic insert-fan-in-diagnostics-20260505-233424.csv. Focused rows remain diagnostic until the release-core suite includes those shapes directly. Full methodology and tuning notes live in the benchmark suite README.


Local SQLite Reference

Same-runner SQLite rows use Microsoft.Data.Sqlite 10.0.7 with WAL + synchronous=FULL. They are comparison points, not universal claims.

Workload CSharpDB SQLite WAL+FULL
Durable prepared bulk insert B1000 211.99K rows/sec 155.66K rows/sec
SQL point lookup 1.48M ops/sec 93.91K ops/sec

Source: sqlite-compare-20260506-035128-median-of-3.csv from the May 6, 2026 release-core snapshot.


Generated Collection Fast Path

The source-generated collection path is opt-in through GetGeneratedCollectionAsync<T>(...). It mainly improves collection payload CPU, direct field extraction, and index-reader paths; one-row durable writes can still be WAL-flush-bound.

Path Source-gen JSON Generated binary Gain Allocation
Encode payload 600.1 ns 306.2 ns 1.96x 552 B to 136 B
Decode payload 2,277.9 ns 371.9 ns 6.12x 1,240 B to 480 B
Indexed int field read 187.23 ns 29.74 ns 6.30x 0 B to 0 B
Text field UTF-8 read 185.82 ns 27.26 ns 6.82x 56 B to 0 B
Key match 21.48 ns 19.91 ns 1.08x 0 B to 0 B

Source: BenchmarkDotNet.Artifacts/results/CSharpDB.Benchmarks.Micro.GeneratedCollection*Benchmarks-report.csv. These rows are diagnostic microbenchmarks, not release-core scorecard rows.


Quick Start

dotnet add package CSharpDB
using CSharpDB.Engine;

// If the file exists, delete it to start fresh
if (File.Exists("mydata.db"))
    File.Delete("mydata.db");

await using var db = await Database.OpenAsync("mydata.db");

await db.ExecuteAsync("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");
await db.ExecuteAsync("INSERT INTO users VALUES (1, 'Alice', 30)");

await using var result = await db.ExecuteAsync("SELECT * FROM users WHERE age > 26");
await foreach (var row in result.GetRowsAsync())
    Console.WriteLine($"{row[0].AsInteger}: {row[1].AsText}, age {row[2].AsInteger}");

Why CSharpDB?

  • No moving parts — single .db file, no server process, no native binaries, no external dependencies
  • SQL + NoSQL in one engine — the documented CSharpDB SQL subset includes JOINs, CTEs, subqueries, views, and triggers, alongside a typed Collection<T> API that bypasses SQL entirely for sub-microsecond reads
  • ACID by default — WAL-based crash recovery with fsync-on-commit and concurrent snapshot-isolated readers
  • Ships with tooling — Admin UI, VS Code extension, CLI REPL, REST API, gRPC daemon, pipeline tooling, integrated forms and reports designers, and MCP server for AI agents
  • Use from any language — NativeAOT compiles to a standalone C library; call from Python, Node.js, Go, Rust, Swift, Kotlin, Dart, Android, and iOS

Admin UI

Querying Table Data Schema
Query tab Data browser Schema view

Blazor Server dashboard with query execution, visual Query Designer, data browser CRUD, schema editing, stored procedures, visual pipeline design, integrated forms and reports designers, backup and maintenance flows, and storage diagnostics.


Ecosystem

CSharpDB is more than an embedded SQL engine. The same database can be used through in-process APIs, remote service hosts, AI tooling, visual designers, and cross-language bindings.

Surface Primary use Highlights
Engine API Embedded in-process access Direct async SQL, transactions, views, triggers, procedures, and query stats
Collection API Typed document and key-value access Collection<T>, nested path indexes, point reads, scans, and path/range queries
ADO.NET Provider Standard .NET data access DbConnection, DbCommand, DbDataReader, and DbTransaction support
Client SDK One C# API across transports Direct, HTTP, and gRPC transports plus maintenance and diagnostics
REST API HTTP integration and automation 30+ endpoints with OpenAPI and Scalar for SQL, schema, data, collections, and maintenance
gRPC Daemon Long-running remote host Strongly typed RPC surface for SQL, schema, procedures, collections, and maintenance
CLI REPL Terminal-first workflows Interactive SQL shell, schema inspection, backup/restore, and migration commands
MCP Server AI assistant integration Tool-based schema inspection, query execution, and row operations for MCP-compatible clients
Admin UI Browser-based database studio Query editor, visual query designer, CRUD, schema editing, procedures, and storage diagnostics
Forms + Reports Internal app workflows and printable output Database-backed forms designer/runtime plus banded reports with grouping, expressions, preview, and print
Pipelines ETL and automation Package-based runtime, visual pipeline designer, transforms, dry-run, checkpoints, and run history
VS Code Extension IDE integration Schema explorer, .csql support, query results, CRUD, and storage diagnostics
Native FFI Polyglot embedding NativeAOT C library for Python, Go, Rust, Swift, Kotlin, Dart, Android, and iOS
Node.js Package JavaScript and TypeScript access Local embedded wrapper over the native library for Node.js apps and tooling

EF Core 10 Provider

CSharpDB includes a first-party embedded EF Core 10 provider for file-backed and private in-memory databases. It supports application-managed concurrency tokens plus one engine-generated nonnullable byte[] [Timestamp]/IsRowVersion() property per table. The opaque eight-byte token is a per-row revision that advances for every successful update, including raw SQL and trigger-issued updates; it is not SQL Server's database-wide counter, and standalone add/alter rowversion migrations remain unsupported. Conventional optional scalar and composite relationships support EF Core's default ClientSetNull: EF clears nullable FK components for tracked dependents, while a restrictive database constraint protects unloaded dependents. Database-side DeleteBehavior.SetNull remains unsupported.

The separate csharpdb-ef migration analyzer can inspect a restored net10.0 project's compiled migration chain through the provider's real design-time services and SQL generator without adding EF Core design dependencies to the base CLI. Generation-only analysis remains the default. Its explicit --scratch tier applies every supported migration prefix to tool-owned private-memory databases, checks normalized schema and history after apply/down/reapply, and twice runs an analyzer-owned guarded replay built from retained Up command payloads. A pass is empty-database evidence only: it does not validate existing-row conversions, file/WAL persistence, configured migration history, locks, interceptors, IMigrator, or IMigrator.GenerateScript behavior.

The supported ASP.NET Core Identity configuration is deliberately bounded to Identity schema v1 with IdentityUser<int> and IdentityRole<int>. Its standard user, role, claim, login, token, role-membership, concurrency, transaction, cancellation, persistence, and cascade workflows are covered by integration tests. The default string-key IdentityDbContext<TUser>, Identity schema versions 2 and 3, passkeys, and unlisted store APIs are not supported. Explicit EF Core transactions support SaveChanges, commit, and rollback; transaction savepoints are explicitly unsupported.

Its supported LINQ surface includes ordinary filtering, ordering, pagination, projections, selected string/temporal/math translations, bounded scalar numeric aggregates, bounded direct inner and left joins, terminal direct-integer set operations, and several deliberately constrained extensions:

  • Ordinal string search for plain string.Contains(string) and for StartsWith, EndsWith, or Contains when the StringComparison argument is the literal StringComparison.Ordinal.
  • Bounded EF.Functions.Like over a direct converter-free TEXT property, with constant or captured patterns and an optional literal one-UTF-16-code-unit escape other than %.
  • Exactly one terminal no-comparer Concat, Union, Intersect, or Except whose two branches each select one compatible, converter-free INTEGER-backed int, long, or nullable equivalent from a direct mapped entity root with optional filtering.
  • One explicit Join between direct entity roots over a nonnullable int, long, or int/long-backed enum key, with supported scalar or entity result projection and post-join filtering, ordering, and pagination.
  • One explicit no-comparer Queryable.LeftJoin over the same direct-root and key surface. Unmatched inner entities and reference members materialize as null; project unmatched inner value-type members to nullable CLR types, such as (int?)inner.Id.
  • Direct single-table GroupBy over mapped scalar or anonymous-type/ValueTuple composite keys, with optional pre-filtering, supported bare numeric aggregates, basic HAVING, and ordering by directly projected keys or aggregates.
  • Where (optional) → selection of one directly mapped nonnullable int column → DistinctCount, LongCount, Sum, Min, or Max.

Distinct Average, nullable or non-int columns, value-converted columns, predicates after Distinct, and transformed or derived distinct shapes are intentionally rejected. In particular, nullable distinct Count/LongCount cannot preserve LINQ's rule that a distinct null is counted once because SQL COUNT(DISTINCT ...) ignores it.

Grouped keys may be direct mapped Boolean, integral, enum, default-BINARY string, or nullable values; Boolean columns must contain canonical provider-written 0/1 storage. Configured key converters and double keys are outside the supported surface. Grouped projections may contain the direct key plus bare Count/LongCount, supported non-distinct Sum/Average/Min/Max, and the same nonnullable-int distinct variants listed above. Transformed keys or results, group materialization, post-projection filters or projections, raw group transforms, nested or joined grouping, predicate aggregates, and unsupported aggregate types or value converters fail before command dispatch with provider diagnostics. See the rowversion contract and EF Core provider guide for the complete boundary.

For both direct join forms, the inner source must be unfiltered; filtered inner roots, prior ordering or row limits, source shapes that remain projected or derived after EF normalization, nullable/text/decimal/transformed/composite keys, and chained joins remain explicitly unsupported. Unsupported direct inner-join shapes report CDBEF1007, and unsupported direct left-join shapes report CDBEF1008. Comparer overloads, the classic GroupJoin/SelectMany/DefaultIfEmpty left-join pattern, RightJoin, and cross-join forms remain unsupported and report the general query-operator diagnostic CDBEF1003.

The supported set operation must be the terminal server-side query. Concat preserves duplicates; Union, Intersect, and Except use distinct set semantics, including one null for nullable projections where appropriate. Ordering is unspecified unless applied after materialization. Entity, composite, constant, converted, or transformed projections; branch ordering, limits, distinct/grouped/derived sources; mixed or non-integer mappings; nested or chained operations; and server-side filtering, projection, ordering, pagination, aggregation, or subquery use after the set operation are rejected before command dispatch with CDBEF1009. The comparer overloads of Union, Intersect, and Except remain unsupported and report CDBEF1003.

String predicates require provider-owned, converter-free TEXT mappings. Ordinal search text may be a constant or parameter and is always treated literally: %, _, and backslash are not wildcard or escape syntax. EF.Functions.Like instead uses % and _ as UTF-16-code-unit wildcards with invariant case-insensitive CSharpDB semantics; its optional escape must be a compile-time one-UTF-16-code-unit literal other than %. Transformed or converted match expressions, row-derived patterns, and captured or invalid escapes fail before command dispatch with CDBEF1001. All other string-search overloads—including default StartsWith(string)/EndsWith(string), the Boolean/CultureInfo forms, non-ordinal or captured StringComparison modes, and character overloads— remain unsupported and fail before command dispatch with CDBEF1001.


Use from Any Language

Node.js:

import { Database } from 'csharpdb';

const db = new Database('mydata.db');
db.execute("INSERT INTO demo VALUES (1, 'Alice')");
for (const row of db.query('SELECT * FROM demo')) console.log(row);
db.close();

Python:

from csharpdb import Database

with Database("mydata.db") as db:
    db.execute("INSERT INTO demo VALUES (1, 'Alice')")
    for row in db.query("SELECT * FROM demo"):
        print(row)

The native library exports 20 C functions. See the Native Library Reference for Go, Rust, Swift, Kotlin, Dart, Android, and iOS examples.


How CSharpDB Compares

Feature CSharpDB SQLite LiteDB RocksDB Microsoft Access
Pure .NET / no native binaries
SQL JOINs, CTEs, and subqueries Partial
NoSQL Collection API
ACID transactions
REST API / gRPC
Admin UI
MCP server (AI agents)
VS Code extension
Multi-language SDKs Partial
Mature ecosystem / battle-tested

Architecture

  SQL string              Collection<T> API
      |                        |
  [Tokenizer]            [JSON serialize]
      |                        |
  [Parser -> AST]         (bypassed)
      |                        |
  [Query Planner]              |
      |                        |
  [Operator Tree]              |
      |                        |
  [B+Tree]  ---------------  [B+Tree]
      |
  [Pager + WAL]              (page cache, write-ahead log)
      |
  [File I/O]                 (4 KB pages, slotted layout)
      |
  mydata.db + mydata.db.wal

Documentation

Getting Started Step-by-step walkthrough
Architecture Guide Engine design deep dive
Tools & Ecosystem APIs, hosts, designers, and integrations
EF Core Provider Embedded EF Core 10 provider guide
Trusted C# Callbacks Register in-process C# functions, commands, and validation rules for SQL, forms, reports, and pipelines
Trusted C# Host Sample VS Code-ready C# host project for trusted functions, commands, validation rules, and form actions
Admin UI Guide Querying, schema, pipelines, forms, reports, and storage
CSharpDB.Client Unified client API and transports
Pipelines ETL package model and visual designer
Reports Visual banded report designer and preview
Native FFI C library API and cross-language examples
REST API Reference HTTP API, schema/data CRUD, and maintenance
MCP Server AI assistant integration
CLI Reference REPL commands
Database Migration Guide Move data from file and database sources, export CSV/JSON, and review mapping, query, and cutover evidence
VS Code Extension Local NativeAOT-backed extension
Benchmark Suite Full results and comparisons
SQL Reference Supported SQL syntax
Internals & Contributing Project structure and concurrency model
FAQ Common questions
Roadmap Project goals

License

MIT

Releases

Packages

Used by

Contributors

Languages