Introduction
ExRam.Gremlinq is a .NET object-graph-mapper (OGM) for Apache TinkerPop™ enabled databases. An OGM is for the realm of graph databases what Entity Framework or NHibernate are for relational databases.
TinkerPop-enabled graph databases are queried by a graph query language called Gremlin. ExRam.Gremlinq enables .NET developers to write and execute these queries in a strongly-typed, fluent C# API mapped to their own domain entity classes. It serializes the query to valid Gremlin for execution on the server and deserializes the results to the correct .NET types.
Features
Type safety
ExRam.Gremlinq queries carry and pass on full information about the query result type and its role (vertex, edge, scalar etc.). This minimizes the possibility of writing and executing invalid queries, speeding up development.
Example
Consider a domain with an Airport vertex class. A plain Gremlin query asking for all airports
in the US looks like this:
ExRam.Gremlinq allows issuing this query using type-safe C# language constructs over the Airport class:
At every step in the query, ExRam.Gremlinq is aware that it is dealing with vertices of type
Airport and, upon retrieval of results from the server, deserializes them into instances of type Airport.
Graph model
ExRam.Gremlinq efficiently manages the type hierarchy of Plain Old CLR Objects (POCOs), offering extensive customization options. Users can tailor member names, adjust type name to label mappings, and easily ignore specific type members. This flexibility ensures seamless integration with database schemas and simplifies data model management.
Powerful DSL
The type system of ExRam.Gremlinq itself, represented as various fluent interfaces that carry result type information, enables developers to rapidly write correct queries.
Example
With Airport vertex and Route edge classes, querying for all airports reachable from JFK reads naturally:
var reachable = await _g
.V<Airport>()
.Where(a => a.Code == "JFK")
.Out<Route>()
.OfType<Airport>()
.ToArrayAsync();
The ExRam.Gremlinq DSL will only allow fluently using the Out<...> method if it knows that it's
currently on a vertex. This avoids accidentally trying to walk edges from e.g. edges or scalar values.
The Gremlin language by itself does not prohibit writing such queries, so that bugs could only
be detected during integration tests or, even worse, in production.
C# expression recognition
ExRam.Gremlinq is capable of recognizing a wide range of C#-expressions and generating valid Gremlin. This enables developers to focus on the business logic in the language they're comfortable with, instead of dealing directly with the intricacies of the Gremlin query language.
Simple example
Querying for all airports whose IATA code starts with the letter "J". Switch the tab to see the corresponding Gremlin.
More complex example
Here's a more complex example showing the power of ExRam.Gremlinq in recognizing expressions that contain an ordinary LINQ method as well as a reference to a step label created earlier in the query.
Inherent thread safety
All query objects and environment structures are immutable. Calling any method on a query returns a new query object; the original is unchanged. As a consequence, queries can be safely shared across threads, stored as fields, and reused without locks or defensive copies.
Customization
ExRam.Gremlinq gives you control over every stage of the pipeline: how queries are serialized, how they are executed, and how results are deserialized. Custom scalar types can be registered to map C# value types to native graph properties, and query execution can be intercepted for logging, retrying, or instrumentation.
Support for Bytecode and Groovy queries
ExRam.Gremlinq supports both Bytecode queries and Groovy scripts. Bytecode is the default for all providers — the query is sent as structured data rather than a string. Groovy scripts are supported for databases that require them, such as Azure CosmosDB.
ASP.NET integration
Dedicated NuGet packages register ExRam.Gremlinq with ASP.NET's dependency injection container,
making IGremlinQuerySource available in middleware and controllers.
Injection-safe by design
When using Bytecode serialization (the default for all providers except CosmosDB), query parameters are sent as structured data alongside the query, never interpolated into a string. There is no Gremlin injection vulnerability equivalent to SQL injection.
Provider support
ExRam.Gremlinq comes with out-of-the-box support for
If you rely on CosmosDb provider packages, follow the transition guide: CosmosDb provider packages transition.
Other providers may just work with the generic Gremlin Server-package, be provided by the community or be part of a paid extension package.