Skip to main content
ClaudeWave
Skill82 repo starsupdated 3d ago

neo4j-driver-dotnet-skill

Neo4j .NET Driver v6 — IDriver lifecycle, DI registration (singleton), ExecutableQuery

Install in Claude Code
Copy
git clone --depth 1 https://github.com/neo4j-contrib/neo4j-skills /tmp/neo4j-driver-dotnet-skill && cp -r /tmp/neo4j-driver-dotnet-skill/neo4j-driver-dotnet-skill ~/.claude/skills/neo4j-driver-dotnet-skill
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

## When to Use
- Writing C# or .NET code connecting to Neo4j
- Setting up `IDriver`, DI registration, or session/transaction lifecycle
- Questions about `ExecutableQuery`, `IResultCursor`, async patterns, result mapping
- Debugging sessions, type mapping, null safety, or error handling in .NET

## When NOT to Use
- **Writing/optimizing Cypher queries** → `neo4j-cypher-skill`
- **Upgrading from older driver version** → `neo4j-migration-skill`

---

## Install

```bash
dotnet add package Neo4j.Driver
```

| Package | Use |
|---|---|
| `Neo4j.Driver` | Async API — **use this** |
| `Neo4j.Driver.Simple` | Synchronous wrapper |
| `Neo4j.Driver.Reactive` | System.Reactive streams |

---

## Driver Lifecycle

`IDriver` — thread-safe, connection-pooled, expensive to create. **Create one per application.**

```csharp
using Neo4j.Driver;

// URI schemes:
//   neo4j+s://xxx.databases.neo4j.io   — TLS + cluster routing (Aura)
//   neo4j://localhost                   — unencrypted + cluster routing
//   bolt+s://localhost:7687             — TLS + single instance
//   bolt://localhost:7687               — unencrypted + single instance

await using var driver = GraphDatabase.Driver(
    "neo4j+s://xxx.databases.neo4j.io",
    AuthTokens.Basic("neo4j", "password"));

await driver.VerifyConnectivityAsync();   // fail fast on startup
```

`IDriver` and `IAsyncSession` implement `IAsyncDisposable` — always `await using`, never plain `using`.

```csharp
// ❌ Wrong — synchronous Dispose() may block thread pool
using var driver = GraphDatabase.Driver(uri, auth);

// ✅ Correct
await using var driver = GraphDatabase.Driver(uri, auth);
```

Auth options: `AuthTokens.Basic(u, p)` / `AuthTokens.Bearer(token)` / `AuthTokens.Kerberos(ticket)` / `AuthTokens.None`

---

## Environment Variables

Load connection config from environment / `appsettings.json` — never hardcode credentials.

```json
// appsettings.json
{
  "Neo4j": {
    "Uri": "neo4j+s://xxx.databases.neo4j.io",
    "User": "neo4j",
    "Password": "secret",
    "Database": "neo4j"
  }
}
```

```csharp
// Access via IConfiguration (injected in Program.cs)
var uri      = builder.Configuration["Neo4j:Uri"];
var user     = builder.Configuration["Neo4j:User"];
var password = builder.Configuration["Neo4j:Password"];
var database = builder.Configuration["Neo4j:Database"] ?? "neo4j";
```

Override with environment variables (standard .NET behavior): `Neo4j__Uri=neo4j+s://...` (double underscore = colon separator). Never commit `appsettings.json` with real credentials — use `appsettings.Development.json` (gitignored) or env vars in CI/production.

---

## DI Registration (ASP.NET Core)

Register `IDriver` as **singleton** — never Scoped or Transient. Never register `IAsyncSession` in DI.

```csharp
// Program.cs
builder.Services.AddSingleton<IDriver>(_ =>
    GraphDatabase.Driver(
        builder.Configuration["Neo4j:Uri"],
        AuthTokens.Basic(
            builder.Configuration["Neo4j:User"],
            builder.Configuration["Neo4j:Password"])));

// Shutdown hook — dispose the singleton cleanly
builder.Services.AddHostedService<Neo4jShutdownService>();

// Neo4jShutdownService.cs
public class Neo4jShutdownService(IDriver driver, IHostApplicationLifetime lifetime)
    : IHostedService
{
    public Task StartAsync(CancellationToken _)
    {
        lifetime.ApplicationStopping.Register(() =>
            driver.DisposeAsync().AsTask().GetAwaiter().GetResult());
        return Task.CompletedTask;
    }
    public Task StopAsync(CancellationToken _) => Task.CompletedTask;
}

// Inject into services — sessions opened per unit of work
public class PersonService(IDriver driver)
{
    public async Task<List<string>> GetNamesAsync(CancellationToken ct = default)
    {
        var (records, _, _) = await driver
            .ExecutableQuery("MATCH (p:Person) RETURN p.name AS name")
            .WithConfig(new QueryConfig(database: "neo4j"))
            .ExecuteAsync(ct);
        return records.Select(r => r.Get<string>("name")).ToList();
    }
}
```

---

## Choose the Right API

| API | When | Auto-retry | Streaming |
|---|---|---|---|
| `driver.ExecutableQuery()` | Most queries — simple default | ✅ | ❌ eager |
| `session.ExecuteReadAsync/WriteAsync()` | Large results, multi-query tx | ✅ | ✅ |
| `session.RunAsync()` | `LOAD CSV`, `CALL {} IN TRANSACTIONS` | ❌ | ✅ |
| `session.BeginTransactionAsync()` | Multi-function, external coordination | ❌ | ✅ |

---

## ExecutableQuery — Recommended Default

Fluent builder; manages session, transaction, retries, and bookmarks automatically.

```csharp
// Read
var (records, summary, keys) = await driver
    .ExecutableQuery("MATCH (p:Person {name: $name})-[:KNOWS]->(f) RETURN f.name AS name")
    .WithParameters(new { name = "Alice" })
    .WithConfig(new QueryConfig(
        database: "neo4j",
        routing: RoutingControl.Readers))    // route reads to replicas
    .ExecuteAsync(cancellationToken);

foreach (var r in records)
    Console.WriteLine(r.Get<string>("name"));

// Use ResultConsumedAfter for wall-clock timing (ResultAvailableAfter = time-to-first-byte only)
Console.WriteLine($"{summary.ResultConsumedAfter.TotalMilliseconds} ms");

// Write
var (_, writeSummary, _) = await driver
    .ExecutableQuery("CREATE (p:Person {name: $name, age: $age})")
    .WithParameters(new { name = "Bob", age = 30 })
    .WithConfig(new QueryConfig(database: "neo4j"))
    .ExecuteAsync();
Console.WriteLine($"Created {writeSummary.Counters.NodesCreated} nodes");

// WithMap — project inline
var names = await driver
    .ExecutableQuery("MATCH (p:Person) RETURN p.name AS name")
    .WithConfig(new QueryConfig(database: "neo4j"))
    .WithMap(r => r["name"].As<string>())
    .ExecuteAsync();   // names.Result is IReadOnlyList<string>
```

Never `await` omitted: `ExecuteAsync()` returns `Task` — missing `await` compiles silently but query never runs.

Never string-interpolate Cypher. Always `WithParameters()` — prevents injection, enables p
neo4j-agent-memory-skillSkill

Authoritative reference for the neo4j-agent-memory Python package — a graph-native memory system for AI agents built on Neo4j — and for the hosted service (NAMS) at memory.neo4jlabs.com. Use this skill whenever the user mentions neo4j-agent-memory, agent memory with Neo4j, context graphs, the POLE+O model, MemoryClient/MemorySettings, the memory MCP server, or any of the framework integrations (LangChain, PydanticAI, CrewAI, AWS Strands, Google ADK, Microsoft Agent Framework, OpenAI Agents, LlamaIndex). Also use when the user mentions the hosted service at memory.neo4jlabs.com, NAMS, the Neo4j Agent Memory Service, the `nams_` API key prefix, or the hosted MCP endpoint. Also use when writing documentation, blog posts, tutorials, PRDs, or code samples for the project, when comparing agent memory approaches, or when positioning graph-native memory against vector-only approaches — even if the user doesn't explicitly name the package.

neo4j-aura-agent-skillSkill

Manages Neo4j Aura Agents via the v2beta1 REST API — create, list, get, update, delete,

neo4j-aura-graph-analytics-skillSkill

Serverless Aura Graph Analytics (AGA) GDS Sessions — covers GdsSessions,

neo4j-aura-provisioning-skillSkill

Provisions and manages Neo4j Aura instances via CLI (aura-cli v1.7+) or REST API.

neo4j-cli-tools-skillSkill

Use when working with Neo4j command-line tools — neo4j-cli (modern unified

neo4j-cypher-skillSkill

Generates, optimizes, and validates Cypher 25 queries for Neo4j 2025.x and 2026.x.

neo4j-document-import-skillSkill

Ingests unstructured and semi-structured documents into Neo4j as a knowledge graph.

neo4j-driver-go-skillSkill

Covers the Neo4j Go Driver v6 — driver lifecycle, ExecuteQuery, managed and