Getting Started
Get CSharpDB up and running in your .NET project in minutes. Choose the API that fits your needs.
Installation
dotnet add package CSharpDB
This meta-package includes the storage engine, SQL engine, Collection API, ADO.NET provider, and diagnostics. For finer control, install individual packages like CSharpDB.Storage, CSharpDB.Engine, or CSharpDB.Data.
Option 1: SQL via ADO.NET
The most familiar approach for .NET developers. Use standard DbConnection, DbCommand, and DbDataReader APIs.
using CSharpDB.Data;
await using var conn = new CSharpDbConnection("Data Source=myapp.db");
await conn.OpenAsync();
// Create a table
await using var cmd = conn.CreateCommand();
cmd.CommandText = @"
CREATE TABLE IF NOT EXISTS Products (
Id INTEGER PRIMARY KEY,
Name TEXT NOT NULL,
Price REAL
)";
await cmd.ExecuteNonQueryAsync();
// Insert rows with parameters
cmd.CommandText = "INSERT INTO Products VALUES (@id, @name, @price)";
cmd.Parameters.Clear();
cmd.Parameters.Add(new CSharpDbParameter("@id", 1));
cmd.Parameters.Add(new CSharpDbParameter("@name", "Widget"));
cmd.Parameters.Add(new CSharpDbParameter("@price", 9.99));
await cmd.ExecuteNonQueryAsync();
// Query
cmd.CommandText = "SELECT Id, Name, Price FROM Products WHERE Price > @minPrice";
cmd.Parameters.Clear();
cmd.Parameters.Add(new CSharpDbParameter("@minPrice", 5.0));
await using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
Console.WriteLine($"{reader.GetString(1)}: ${reader.GetDouble(2):F2}");
}
Option 2: Engine API with SQL
Use the Database class directly for a lightweight, high-performance approach.
using CSharpDB.Engine;
await using var db = await Database.OpenAsync("myapp.db");
// Execute SQL directly
await db.ExecuteAsync(@"
CREATE TABLE Users (
Id INTEGER PRIMARY KEY,
Name TEXT NOT NULL,
Email TEXT
)");
await db.ExecuteAsync("INSERT INTO Users VALUES (1, 'Alice', 'alice@example.com')");
await db.ExecuteAsync("INSERT INTO Users VALUES (2, 'Bob', 'bob@example.com')");
await using var results = await db.ExecuteAsync("SELECT Name, Email FROM Users ORDER BY Name");
while (await results.MoveNextAsync())
{
Console.WriteLine($"{results.Current[0].AsText}: {results.Current[1].AsText}");
}
Option 3: Collection API (NoSQL)
Work with typed C# objects — no SQL needed. Built-in JSON serialization and indexing.
using CSharpDB.Engine;
public record Product(string Name, double Price, string[] Tags);
await using var db = await Database.OpenAsync("myapp.db");
var products = await db.GetCollectionAsync<Product>("products");
// Store objects
await products.PutAsync("widget", new("Widget", 9.99, ["tools", "hardware"]));
await products.PutAsync("gadget", new("Gadget", 24.99, ["electronics"]));
// Retrieve
var widget = await products.GetAsync("widget");
// Index a property and query
await products.EnsureIndexAsync(p => p.Name);
await foreach (var match in products.FindByIndexAsync(p => p.Name, "Gadget"))
Console.WriteLine(match.Key);
// Scan all
await foreach (var entry in products.ScanAsync())
Console.WriteLine($"{entry.Key}: {entry.Value.Name}: ${entry.Value.Price:F2}");
Option 4: Low-Level Storage API
For maximum control, use the storage engine directly with B+trees, pages, and the WAL.
using CSharpDB.Storage.BTrees;
using CSharpDB.Storage.Paging;
using CSharpDB.Storage.StorageEngine;
var storageOptions = new StorageEngineOptionsBuilder()
.UsePagerOptions(new PagerOptions { MaxCachedPages = 1024 })
.UseBTreeIndexes()
.Build();
var factory = new DefaultStorageEngineFactory();
await using var ctx = await factory.OpenAsync("myapp.db", storageOptions);
await ctx.Pager.BeginTransactionAsync();
try
{
uint rootPageId = await BTree.CreateNewAsync(ctx.Pager);
var tree = new BTree(ctx.Pager, rootPageId);
await tree.InsertAsync(1, new byte[] { 1, 2, 3, 4 });
byte[]? payload = await tree.FindAsync(1);
await ctx.Pager.CommitAsync();
}
catch
{
await ctx.Pager.RollbackAsync();
throw;
}
Custom Configuration
Fine-tune the storage engine for your workload.
using CSharpDB.Engine;
var options = new DatabaseOptions()
.ConfigureStorageEngine(builder =>
{
builder.UseDirectLookupOptimizedPreset();
});
await using var db = await Database.OpenAsync("myapp.db", options);
// Also available: in-memory and hybrid modes
await using var mem = await Database.OpenInMemoryAsync();
await using var hybrid = await Database.OpenHybridAsync(
"myapp.db",
new DatabaseOptions(),
new HybridDatabaseOptions
{
PersistenceMode = HybridPersistenceMode.IncrementalDurable,
HotTableNames = ["Products"]
});