This client follows the Dgraph Go client closely.
Before using this client, we highly recommend that you go through dgraph.io/docs, and understand how to run and work with Dgraph.
Use Discuss Issues for reporting issues about this repository.
Install using nuget:
dotnet add package Dgraph
WARNING: Be aware that there may be other .NET packages with similar names. To verify the official package, please visit https://www.nuget.org/packages/Dgraph. Make sure you are using the correct and official package to avoid potential confusion.
Depending on the version of Dgraph that you are connecting to, you will have to use a different version of this client.
Dgraph version | Dgraph.net version |
---|---|
dgraph 21.X.Y | Dgraph.net 21.3.1.2 |
dgraph 23.X.Y | Dgraph.net 23.0.0 |
Most client and transaction methods return a Result
object from the
FluentResults library. You can check the status
of the result by using Result.IsSuccess
or Result.IsFailed
. Exceptions are contained
inside Result.Errors
.
An IDgraphClient
can be created with a list of GrpcChannel
as objects. Connecting
to multiple Dgraph servers in the same cluster allows for better distribution of workload.
The following code snippet shows just one connection.
using Dgraph;
using Grpc.Net.Client;
GrpcChannel channel = GrpcChannel.ForAddress("http://localhost:9080");
using var dgraphClient = DgraphClient.Create(channel);
The connection can be configured by using GrpcChannelOptions
.
using Grpc.Net.Client;
var options = new GrpcChannelOptions
{
CompressionProviders = <...>, // List of Grpc ICompressionProvider
Credentials = Grpc.Core.ChannelCredentials.Create(<...>)
};
GrpcChannel channel = GrpcChannel.ForAddress("http://localhost:9080", options);
If your server has Access Control Lists enabled (Dgraph v1.1 or above), the client must be
logged in for accessing data. Use Login
to obtain and remember access and refresh JWTs.
var response = await dgraphClient.Login("user", "password");
if (response.IsFailed) {
// Handle errors
}
All subsequent operations via the logged in client will send along the stored access token.
If your server additionally has namespaces (Dgraph v21.03 or above), use LoginIntoNamespace
.
var response = await dgraphClient.LoginIntoNamespace("groot", "password", 123);
if (response.IsFailed) {
// Handle errors
}
Use DgraphCloudChannel.Create
to create a GrpcChannel that connects to a Dgraph Cloud
backend.
DgraphCloudChannel.Create
can accept GraphQL or gRPC URIs from
Dgraph Cloud, but it will always connect via gRPC.
using Dgraph;
using Grpc.Net.Client;
string ENDPOINT = "<...>";
string API_KEY = "<...>";
GrpcChannel channel = DgraphCloudChannel.Create(ENDPOINT, API_KEY);
using var dgraphClient = DgraphClient.Create(channel);
To set the schema, create an instance of Dgraph.Api.Operation
and use the Alter
endpoint.
using Dgraph;
var operation = new Api.Operation {
Schema = "name: string @index(exact) ."
};
var response = await dgraphClient.Alter(operation);
if (response.IsFailed) {
// Handle errors
}
Operation
contains other fields as well, including DropAttr
and DropAll
.
DropAll
is useful if you wish to discard all the data without bringing the instance
down. DropAttr
is used to drop all the data related to a predicate.
Starting in Dgraph version 20.03.0, indexes can be computed in the background. You can
set the RunInBackground
field to true
like so:
using Dgraph;
var operation = new Api.Operation {
Schema = "name: string @index(exact) .",
RunInBackground = true
};
var response = await dgraphClient.Alter(operation);
if (response.IsFailed) {
// Handle errors
}
To create a transaction, call the IDgraphClient.NewTransaction()
method, which returns
a new ITransaction
. This operation incurs no network overhead.
To ensure the ITransaction
is properly disposed after it has completed, use the
using
keyword.
using var transaction = dgraphClient.NewTransaction();
var transactionResponse = await transaction.Mutate(...);
if (transactionResponse.IsFailed) {
// Handle errors
}
var response = await transaction.Commit();
if (response.IsFailed) {
// Handle errors
}
Read-only transactions can be created by calling the IDgraphClient.NewReadOnlyTransaction
method. Read-only transactions are useful to increase read speed because they can circumvent
the usual consensus protocol. Read-only transactions cannot contain mutations. There is
nothing to dispose for a ReadOnlyTransaction
object, so it does not implement IDisposable
.
var readOnlyTransaction = dgraphClient.NewReadOnlyTransaction();
var response = await readOnlyTransaction.Query(...);
if (response.IsFailed) {
// Handle errors
}
ITransaction.Mutate
runs a mutation. It takes a Dgraph.Api.Mutation
or a MutationBuilder
.
You can set the data using JSON or RDF N-Quad format.
To use JSON, use the fields SetJson
and DeleteJson
, which accept a string representing the
nodes to be added or removed respectively (either as a JSON map or a list). You can use any
library to serialize objects to a JSON string, such as JSON.NET.
To use RDF, use the fields SetNquads
and DelNquads
, which accept a string representing the
valid RDF triples (one per line) to be added or removed respectively.
Dgraph.Api.Mutation
also contains the Set
and Del
fields which accept a list of RDF
triples that have already been parsed into our internal format. As such, these fields are
mainly used internally and you should use the SetNquads
and DelNquads
fields instead
if you plan on using RDF.
While you can construct a Dgraph.Api.Mutation
object directly, it is easier to let MutationBuilder
handle implementation details like converting string
to Google.Protobuf.ByteString
.
using Dgraph;
var transaction = dgraphClient.NewTransaction();
var mutation = new MutationBuilder().SetJson("...").CommitNow();
var response = await transaction.Mutate(mutation);
if (response.IsFailed) {
// Handle errors
}
If you want to commit a mutation without querying anything further, use MutationBuilder.CommitNow
to indicate that the transaction must be immediately committed.
var mutation = new MutationBuilder().SetJson("...").CommitNow();
Multiple mutations can be run in a single request using ITransaction.Do
and RequestBuilder
.
To immediately commit the request, use RequestBuilder.CommitNow
.
using Dgraph;
var transaction = dgraphClient.NewTransaction();
var request = new RequestBuilder().WithMutations(
new MutationBuilder().SetJson("..."),
new MutationBuilder().SetJson("..."),
new MutationBuilder().SetJson("..."),
);
var response = await transaction.Do(request);
if (response.IsFailed) {
// Handle errors
}
Keep in mind that if you do not use RequestBuilder.CommitNow
or MutationBuilder.CommitNow
,
you will still need to manually commit the transaction using ITransaction.Commit
.
Check out the example in source/Dgraph.tests.e2e/TransactionTest.cs
.
You can run a query by calling ITransaction.Query
. You will need to pass in a DQL query
string. If you want to pass an additional map of any variables that you might want to set
in the query, call ITransaction.QueryWithVars
with the variables dictionary as the second
argument.
Let’s run the following query with a variable $a:
var query = @"
query all($a: string) {
all(func: eq(name, $a)) {
name
}
}";
var varMap = new Dictionary<string, string> { { "$a", "Alice" } };
var response = await transaction.QueryWithVars(query, varMap);
if (response.IsFailed) {
// Handle errors
}
You can also use ITransaction.Do
to run a query.
var query = @"
query all($a: string) {
all(func: eq(name, $a)) {
name
}
}";
var varMap = new Dictionary<string, string> { { "$a", "Alice" } };
var request = new RequestBuilder().WithQuery(query).WithVars(varMap);
var response = await transaction.Do(request);
if (response.IsFailed) {
// Handle errors
}
When running a schema query for predicate name
, the schema response is found in the
Json
field of the transaction response:
var query = @"
schema(pred: [name]) {
type
index
reverse
tokenizer
list
count
upsert
lang
}";
var response = await transaction.Query(query);
if (response.IsSuccess) {
Console.WriteLine(response.Value.Json);
}
You can get query results as a RDF response by calling ITransaction.QueryRdf
. The Rdf
field in the response has the encoded RDF result.
Note: If you are querying for only uid
values, use a JSON format response.
// Query the balance for Alice and Bob.
var query = @"
{
all(func: anyofterms(name, ""Alice Bob"")) {
name
balance
}
}";
var response = await transaction.QueryRDF(query);
if (response.IsSuccess) {
// <0x17> <name> "Alice" .
// <0x17> <balance> 100 .
Console.WriteLine(response.Value.Rdf);
}
ITransaction.QueryRDFWithVars
is also available when you need to pass values for variables
used in the query.
The ITransaction.Do
method allows you to run upserts consisting of one query and one
mutation. Variables can be defined in the query and used in the mutation.
To know more about upsert, we highly recommend going through the docs at Upsert Block
var query = @"
query {
user as var(func: eq(email, ""[email protected]""))
}";
var mutation = new MutationBuilder().SetNquads("uid(user) <email> \"[email protected]\" .");
var request = new RequestBuilder()
.WithQuery(query)
.WithMutations(mutation)
.CommitNow();
// Update email only if matching uid found.
var response = await transaction.Do(request);
if (response.IsFailed) {
// Handle errors
}
The upsert block also allows specifying a conditional block using and @if
directive.
The mutation is executed only when the specified condition is true. If the condition
is false, the mutation is silently ignored.
See more about Conditional Upsert here.
var query = @"
query {
user as var(func: eq(email, ""[email protected]""))
}";
var mutation = new MutationBuilder()
.Cond("@if(eq(len(user), 1))") // Only mutate if "[email protected]" belongs to single user.
.SetNquads("uid(user) <email> ""correct_email@dgraph.io"" .");
var request = new RequestBuilder()
.WithQuery(query)
.WithMutations(mutation)
.CommitNow();
// Update email only if exactly one matching uid found.
var response = await transaction.Do(request);
if (response.IsFailed) {
// Handle errors
}
A transaction can be committed using the ITransaction.Commit
method. If your
transaction never submitted any mutations, then ITransaction.Commit
is not necessary.
An error will be returned if other transactions running concurrently modify the same data that was modified in this transaction. It is up to the user to retry transactions when they fail.
using var transaction = dgraphClient.NewTransaction();
// Perform some queries and mutations.
var response = await transaction.Commit();
if (response.IsFailed) {
// Retry or handle errors
}
Metadata headers such as authentication tokens can be set through the options
argument of gRPC methods. Below is an example of how to set a header named "auth-token".
using Grpc.Core;
var metadata = new Metadata
{
{ "auth-token", "the-auth-token-value" }
};
var options = new CallOptions(headers: metadata);
client.Alter(operation, options);