Downloadable open-source computer software from CVOYA. See the CVOYA software catalog.
Download the current CVOYA Graph source (.zip)
A powerful, type-safe .NET library ecosystem for working with graph data structures and graph databases. CVOYA Graph provides a clean abstraction layer over graph databases with advanced LINQ querying, transaction management, and relationship traversal capabilities.
- 🔒 Type-Safe Graph Operations - Work with strongly-typed nodes and relationships using modern C# features
- 🔍 Advanced LINQ Support - Query your graph using familiar LINQ syntax with graph-specific extensions
- 🔄 Graph Traversal & Path Finding - Navigate complex relationships with depth control and direction constraints
- ⚡ Transaction Management - Full ACID transaction support with async/await patterns
- 🎯 Provider Architecture - Clean abstraction supporting multiple graph database backends
- 📊 Neo4j Integration - Complete Neo4j implementation with LINQ-to-Cypher translation
- 🐘 Apache AGE Integration - PostgreSQL provider built on the shared Cypher dialect SPI
- 🛡️ Compile-Time Validation - Code analyzers ensure that the data model requirements
- 🏗️ Complex Object Serialization - Automatic handling of complex properties and circular references
- 📈 Build-time code generation - Automatic code generation for efficient serialization/deserialization of domain data types
- 🎨 Attribute-Based Configuration - Configure nodes and relationships using intuitive attributes
To get started, install the provider package for your graph database:
The Cvoya.Graph.* package IDs will be published by CVOYA with the next release. Earlier
Cvoya.Graph.Model.* packages remain available on the CVOYA NuGet profile.
Building your own provider? See Certifying a provider for how to run the shared compatibility suite against it.
# Install the Neo4j provider (required)
dotnet add package Cvoya.Graph.Neo4j
# Optionally, add code analyzers for extra compile-time validation (recommended)
dotnet add package Cvoya.Graph.Analyzersusing Cvoya.Graph;
[Node("Person")]
public record Person : Node
{
[Property(Label = "first_name", IsIndexed = true)]
public string FirstName { get; set; } = string.Empty;
[Property(Label = "last_name", IsIndexed = true)]
public string LastName { get; set; } = string.Empty;
// The Property attribute is optional
public int Age { get; set; }
public Address? HomeAddress { get; set; } // Complex types supported
}
// When used as the type of a property, it makes that property a "complex property"
public class Address
{
public string Street { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
public string Country { get; set; } = string.Empty;
public Point? Coordinates { get; set; } // Spatial data
}
[Relationship("KNOWS")]
public record Knows(string StartNodeId, string EndNodeId) : Relationship(StartNodeId, EndNodeId)
{
public DateTime Since { get; set; }
// Relationships cannot have complex properties
}For your convenience, the Cvoya.Graph package also offers Node and Relationship records so that you only have to focus on your domain-specific properties:
Prefer these base records in application models; implementing INode or IRelationship directly triggers analyzer warning CG011 unless you need full control.
public record Person : Node
{
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public int Age { get; set; }
public Address? HomeAddress { get; set; }
}
public record Knows(string StartNodeId, string EndNodeId) : Relationship(StartNodeId, EndNodeId)
{
public DateTime Since { get; set; }
}or:
public record Knows : Relationship
{
public Knows() : base(Guid.NewGuid().ToString("N"), Guid.NewGuid().ToString("N")) { }
public Knows(Person p1, Person p2) : base(p1.Id, p2.Id) {}
public DateTime Since { get; set; }
}using Cvoya.Graph.Neo4j;
// Neo4j provider
var store = new Neo4jGraphStore(
uri: "bolt://localhost:7687",
username: "neo4j",
password: "password",
databaseName: "myapp"
);
var graph = store.Graph;// Create nodes
var alice = new Person
{
FirstName = "Alice",
LastName = "Smith",
Age = 30,
HomeAddress = new Address
{
Street = "123 Main St",
City = "Portland",
Country = "USA"
}
};
await graph.CreateNodeAsync(alice);
// Create relationships
var bob = new Person { FirstName = "Bob", LastName = "Jones", Age = 25 };
await graph.CreateNodeAsync(bob);
var friendship = new Knows(alice.Id, bob.Id)
{
Since = DateTime.UtcNow.AddYears(-2)
};
await graph.CreateRelationshipAsync(friendship);
// Query with LINQ
var youngPeople = await graph.Nodes<Person>()
.Where(p => p.Age < 30)
.Where(p => p.HomeAddress != null && p.HomeAddress.City == "Portland")
.OrderBy(p => p.FirstName)
.ToListAsync();
// Graph traversal
var alicesFriends = await graph.Nodes<Person>()
.Where(p => p.FirstName == "Alice")
.Traverse<Knows, Person>(minDepth: 1, maxDepth: 2)
.Where(friend => friend.Age > 20)
.ToListAsync();await using var transaction = await graph.GetTransactionAsync();
try
{
await graph.CreateNodeAsync(person, transaction: transaction);
await graph.CreateRelationshipAsync(relationship, transaction: transaction);
await transaction.CommitAsync();
}
catch
{
await transaction.RollbackAsync();
throw;
}- API Reference - Generated API documentation for all packages
- Core Concepts - Understanding nodes, relationships, and entities
- LINQ Querying - Advanced query patterns and graph traversal
- Transaction Management - Working with ACID transactions
- Attributes & Configuration - Customizing nodes and relationships
- Best Practices - Performance tips and patterns
- Provider Implementers Guide - Current provider SPI, storage conventions, and contract-test reuse
- Neo4j Provider - Neo4j-specific features and configuration
- Code Analyzers - Compile-time validation rules
- Code Generation - Build-time code generation for serialization
- Troubleshooting - In case you encounter issues
- Building Graph Model - Building the projects in this repository
- AI agent documentation - Where to find context for Claude Code, Codex, Copilot, and other AI coding tools
Explore comprehensive examples in the examples/ directory:
- Basic Serialization - CRUD operations and complex object handling
- Basic CRUD - Fundamental create, read, update, delete operations
- LINQ & Traversal - Advanced querying and graph navigation
- Transaction Management - ACID transactions and rollback scenarios
- Advanced Scenarios - Complex patterns and optimizations
- Social Network - Real-world social graph implementation
- Full Text Search - Search across nodes and relationships
- Simple Movie Example - Compact movie graph walkthrough
CVOYA Graph supports multiple build configurations for different scenarios:
# Development (fastest, project references)
dotnet build --configuration Debug
# Local package-reference validation before publishing
dotnet msbuild eng/PackageValidation.proj -target:Validate
# Production package build (pack builds first by default)
dotnet pack src/Graph/Graph.csproj --configuration ReleaseFor testing package references locally before publishing to NuGet:
# Pack the complete LocalFeed set, verify it, then restore and build with package references
dotnet msbuild eng/PackageValidation.proj -target:Validate
# Remove only repository-scoped package-validation state
dotnet msbuild eng/PackageValidation.proj -target:CleanSee Build System Documentation for complete details.
CVOYA Graph follows a clean, layered architecture:
┌─────────────────────────────────┐
│ Your Application │
├─────────────────────────────────┤
│ Graph (Core) │ ← Abstractions & LINQ
├─────────────────────────────────┤
│ Cvoya.Graph.Neo4j │ ← Provider Implementation
├─────────────────────────────────┤
│ Neo4j Database │ ← Storage Layer
└─────────────────────────────────┘
Key Components:
- IGraph - Main entry point for all graph operations
- INode / IRelationship - Type-safe entity contracts
- IGraphQueryable - LINQ provider with graph-specific extensions
- IGraphTransaction - ACID transaction management
- Attributes - Declarative configuration (Node, Relationship, Property)
- .NET 10.0 or later
- Neo4j 5.x (for the Neo4j provider)
- C# 14 language features
- Blog Post: CVOYA graph: A .NET Abstraction for Graphs
- Blog Post: Playing with graphs and neo4j by Savas Parastatidis
- Neo4j Documentation
- Graph Database Concepts
This repo provides context for AI coding agents (Claude Code, Codex, Copilot, and others). The canonical instruction set is AGENTS.md; see docs/ai-agents.md for the per-tool map.
We welcome contributions! Please see our Contributing Guidelines for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Licensed under the Apache License, Version 2.0. See LICENSE for details.
Special thanks to the Neo4j team for creating an excellent graph database and driver ecosystem that makes this library possible.
Built by Savas Parastatidis at CVOYA.