Managed .NET wrapper for the Traverse embedded graph database.
$ dotnet add package Traverse.EmbeddedManaged .NET 10 wrapper for the Traverse embedded graph database. Query your data with Cypher, visualize with Sigma.js — no server required. If you want a server visit the docs and download for your OS.
dotnet add package Traverse.Embedded
using Traverse;
// Open (or create) a database — unlicensed (no write limits)
using var db = Database.Open("my-graph.tvdb");
// Or open with a license key (enforces plan limits on writes)
using var db = Database.OpenLicensed("my-graph.tvdb", "tskey_...");
// Write data inside a transaction
using (var tx = db.BeginTransaction())
{
tx.Query("CREATE (a:Person {name: 'Alice', age: 30})");
tx.Query("CREATE (b:Person {name: 'Bob', age: 25})");
tx.Query("""
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CREATE (a)-[:KNOWS {since: 2020}]->(b)
""");
tx.Commit();
}
// Read data
using (var tx = db.BeginTransaction())
{
using var result = tx.Query("MATCH (p:Person) RETURN p.name, p.age ORDER BY p.age");
foreach (var row in result)
{
Console.WriteLine($"{row.GetString("p.name")} is {row.GetInt64("p.age")} years old");
}
// Output:
// Bob is 25 years old
// Alice is 30 years old
tx.Abort();
}
// Open or create a database file
using var db = Database.Open("path/to/graph.tvdb");
// Or open with a license key (validates against Traverse API,
// enforces plan limits on node/edge creation)
using var db = Database.OpenLicensed("path/to/graph.tvdb", "tskey_...");
// Flush dirty pages to disk
db.Flush();
// Begin a write transaction
using var tx = db.BeginTransaction();
// Execute a Cypher query
using var result = tx.Query("MATCH (n:Person) RETURN n.name");
// Commit changes
tx.Commit();
// Or abort (also happens automatically on Dispose if not committed)
tx.Abort();
using var result = tx.Query("RETURN 1 AS x, 'hello' AS y");
// Metadata
int cols = result.ColumnCount; // 2
long rows = result.RowCount; // 1
string name = result.Columns[0].Name; // "x"
// Iterate rows (forward-only cursor)
foreach (var row in result)
{
long x = row.GetInt64("x");
string y = row.GetString("y");
}
// Or snapshot all rows into a list (safe to use after enumeration)
List<Row> allRows = result.ToList();
// Typed accessors — by column index or name
string? s = row.GetString(0);
long i = row.GetInt64("count");
double d = row.GetDouble(2);
bool b = row.GetBool("flag");
bool nil = row.IsNull(0);
string t = row.GetTypeName(0); // "INTEGER", "STRING", "NODE", etc.
object? v = row.GetValue(0); // Boxed typed value
// Snapshot: copy all values into managed memory
// (the live row is only valid during the current iteration)
Row snapshot = row.Snapshot();
Non-transactional bulk writer for high-throughput graph loading. Bypasses MVCC for maximum write speed — no other transactions or bulk writers may be active at the same time.
using var bulk = db.BeginBulkWrite();
// Create nodes (property values are auto-inferred from strings)
var alice = bulk.CreateNode(["Person"], ["name", "age"], ["Alice", "30"]);
var bob = bulk.CreateNode(["Person"], ["name", "age"], ["Bob", "25"]);
// Create edges
bulk.CreateEdge(alice, bob, "KNOWS", ["since"], ["2020"]);
// Create indexes
bulk.CreateIndex("idx_person_name", "Person", "name");
bulk.CreateEdgeIndex("idx_knows_since", "KNOWS", "since");
bulk.Commit(); // or Abort(); auto-aborts on Dispose if not committed
Traverse is fully in-memory. By default, Database.Open rejects files larger than 80% of physical RAM to prevent OOM:
// Adjust or disable the safety limit
Database.MaxFileSizeBytes = 16L * 1024 * 1024 * 1024; // 16 GB
Database.MaxFileSizeBytes = 0; // disable check
Serialize query results to graphology-compatible JSON for use with Sigma.js:
using (var tx = db.BeginTransaction())
{
using var result = tx.Query("MATCH (a)-[e]->(b) RETURN a, e, b");
string json = GraphJsonSerializer.Serialize(result);
// Returns: {"nodes":[...],"edges":[...]}
tx.Abort();
}
Output format:
{
"nodes": [
{
"key": "n0",
"attributes": {
"label": "Person",
"name": "Alice",
"labels": ["Person"]
}
}
],
"edges": [
{
"key": "e0",
"source": "n0",
"target": "n1",
"attributes": {
"label": "KNOWS"
}
}
]
}
Load this directly into a Sigma.js graph:
import Graph from "graphology";
import Sigma from "sigma";
const graph = new Graph();
const data = await fetch("/api/graph").then(r => r.json());
graph.import(data);
new Sigma(graph, document.getElementById("container"));
All native errors are surfaced as TraverseException with a typed ErrorCode:
try
{
tx.Query("INVALID CYPHER");
}
catch (TraverseException ex) when (ex.ErrorCode == TvErrorCode.Syntax)
{
Console.WriteLine($"Syntax error: {ex.Message}");
}
The NuGet package bundles the native Traverse library under runtimes/<rid>/native/. Supported platforms:
| Runtime ID | Library |
|---|---|
win-x64 | traverse_ffi.dll |
linux-x64 | libtraverse_ffi.so |
osx-arm64 | libtraverse_ffi.dylib |
Full documentation at truespar.com/traverse/docs
Copyright 2025-2026 Truespar. All rights reserved.