Skip to content

cvoya-com/graph

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

504 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

CVOYA Graph

Downloadable open-source computer software from CVOYA. See the CVOYA software catalog.

Download the current CVOYA Graph source (.zip)

License .NET GitHub release CI Documentation Codecov CodeQL Contributors Issues Stars

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.

Features

  • 🔒 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

Packages

To get started, install the provider package for your graph database:

Package Description NuGet
Cvoya.Graph.Neo4j Neo4j provider implementation NuGet
Cvoya.Graph.Age PostgreSQL + Apache AGE provider implementation NuGet
Cvoya.Graph.InMemory In-memory reference provider and test double NuGet
Cvoya.Graph Core abstractions and interfaces NuGet
Cvoya.Graph.Cypher Shared typed Cypher model and rendering infrastructure NuGet
Cvoya.Graph.Analyzers Compile-time code analyzers (optional, recommended) NuGet
Cvoya.Graph.Serialization.CodeGen Compile-time code generation NuGet
Cvoya.Graph.Serialization Serialization-related functionality NuGet
Cvoya.Graph.CompatibilityTests Provider compatibility test suite (optional, provider authors) NuGet

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.

Quick Start

1. Installation

# 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.Analyzers

2. Define Your Domain Model

using 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; }
}

3. Create Graph Instance

using Cvoya.Graph.Neo4j;

// Neo4j provider
var store = new Neo4jGraphStore(
    uri: "bolt://localhost:7687",
    username: "neo4j",
    password: "password",
    databaseName: "myapp"
);
var graph = store.Graph;

4. Basic Operations

// 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();

5. Transaction Management

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;
}

Documentation

Examples

Explore comprehensive examples in the examples/ directory:

Building & Testing

Build Configurations

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 Release

For 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:Clean

See Build System Documentation for complete details.

Architecture

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)

Requirements

  • .NET 10.0 or later
  • Neo4j 5.x (for the Neo4j provider)
  • C# 14 language features

Related Resources

AI agent documentation

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.

Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

Licensed under the Apache License, Version 2.0. See LICENSE for details.

Acknowledgments

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.

About

An abstraction for a Graph that supports LINQ expressions.

Resources

License

Code of conduct

Contributing

Security policy

Stars

11 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors