A fluent API extension for Neo4jClient that simplifies building Cypher queries using strongly-typed C# objects.
- Type-Safe Query Building - Create, match, and merge nodes and relationships using objects instead of writing Cypher strings
- Fluent Configuration - Configure entity metadata without cluttering domain models with attributes
- Relationship Modeling - Strongly-typed relationships with properties
- IntelliSense Support - Full IDE autocomplete for improved productivity
- Reduced Errors - Compile-time checking prevents property name typos and refactoring issues
CreateEntity<T>- Create nodes from objectsMergeEntity<T>- Merge nodes with ON CREATE/ON MATCH supportMatchEntity<T>- Match nodes by propertiesCreateRelationship<T>- Create typed relationshipsMergeRelationship<T>- Merge relationshipsMatchRelationship<T>- Match relationships
# Install Neo4jClient
dotnet add package Neo4jClient
# Install Neo4jClient.Extension
dotnet add package Neo4jClient.Extensionusing Neo4jClient;
using Neo4jClient.Extension.Cypher;
// Connect to Neo4j
var client = new BoltGraphClient(new Uri("bolt://localhost:7687"), "neo4j", "password");
await client.ConnectAsync();
// Configure your entities (do this once at startup)
FluentConfig.Config()
.With<Person>()
.Match(x => x.Id)
.Merge(x => x.Id)
.MergeOnCreate(p => p.DateCreated)
.Set();Configure entity metadata once at application startup without decorating your domain models:
FluentConfig.Config()
.With<Person>("SecretAgent")
.Match(x => x.Id)
.Merge(x => x.Id)
.MergeOnCreate(p => p.DateCreated)
.MergeOnMatchOrCreate(p => p.Name)
.MergeOnMatchOrCreate(p => p.Title)
.Set();Configure relationships with properties:
FluentConfig.Config()
.With<HomeAddressRelationship>()
.MergeOnMatchOrCreate(hr => hr.DateEffective)
.Set();var person = new Person { Id = 1, Name = "John Doe" };
await client.Cypher
.CreateEntity(person, "p")
.ExecuteWithoutResultsAsync();var person = new Person { Id = 1, Name = "John Doe" };
var address = new Address { Street = "123 Main St", City = "Austin" };
await client.Cypher
.CreateEntity(person, "p")
.CreateEntity(address, "a")
.CreateRelationship(new HomeAddressRelationship("p", "a"))
.ExecuteWithoutResultsAsync();var person = new Person { Id = 1, Name = "John Doe", DateCreated = DateTime.UtcNow };
await client.Cypher
.MergeEntity(person) // Uses configured Merge properties
.MergeEntity(person.HomeAddress)
.MergeRelationship(new HomeAddressRelationship("person", "homeAddress"))
.ExecuteWithoutResultsAsync();For those who prefer attributes, you can decorate your models directly:
[CypherLabel(Name = "Person")]
public class Person
{
[CypherMerge]
public Guid Id { get; set; }
[CypherMergeOnCreate]
public string Name { get; set; }
[CypherMergeOnMatchOrCreate]
public bool IsActive { get; set; }
}Available Attributes:
CypherLabel- Custom node label (defaults to class name)CypherMatch- Used in MATCH clausesCypherMerge- Used in MERGE clausesCypherMergeOnCreate- Set only when creating (ON CREATE SET)CypherMergeOnMatch- Set only when matching (ON MATCH SET)
Note: Fluent configuration is recommended to keep domain models infrastructure-free.
Define strongly-typed relationships by inheriting from BaseRelationship:
[CypherLabel(Name = "HOME_ADDRESS")]
public class HomeAddressRelationship : BaseRelationship
{
public HomeAddressRelationship(string fromKey, string toKey)
: base(fromKey, toKey) { }
public DateTime DateEffective { get; set; }
}dotnet build Neo4jClient.Extension.slnUnit Tests:
dotnet test test/Neo4jClient.Extension.UnitTest/Integration Tests (requires Neo4j):
# Automated setup (recommended)
./run-tests-with-neo4j.sh # Linux/macOS
run-tests-with-neo4j.bat # Windows
# Manual setup
docker compose up -d neo4j
dotnet test --filter Integration
docker compose downpowershell -f build.ps1 -packageVersion 1.0.0Output: ./_output/ directory
- CLAUDE.md - Comprehensive architecture documentation
- DOCKER-TESTING.md - Docker setup for integration tests
- Unit Tests - Usage examples
- .NET 9.0 or later
- Neo4jClient 4.0.0+
- Neo4j 5.x (for integration tests)
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the terms specified in the LICENSE file.