Once ready, add the SurrealDB SDK to your dependencies:
dotnet add package SurrealDb.Net
Let’s start by creating a new console app.
dotnet new console -o SurrealDbExample cd SurrealDbExample dotnet add package SurrealDb.Net
Open Program.cs
and replace everything in there with the following code to try out some basic operations using the SurrealDB SDK.
using SurrealDb.Net; using SurrealDb.Net.Models; using SurrealDb.Net.Models.Auth; using System.Text.Json; const string TABLE = "person"; var db = new SurrealDbClient("ws://127.0.0.1:8000/rpc"); await db.SignIn(new RootAuth { Username = "root", Password = "root" }); await db.Use("test", "test"); var person = new Person { Title = "Founder & CEO", Name = new() { FirstName = "Tobie", LastName = "Morgan Hitchcock" }, Marketing = true }; var created = await db.Create(TABLE, person); Console.WriteLine(ToJsonString(created)); var updated = await db.Merge<ResponsibilityMerge, Person>( new() { Id = (TABLE, "jaime"), Marketing = true } ); Console.WriteLine(ToJsonString(updated)); var people = await db.Select<Person>(TABLE); Console.WriteLine(ToJsonString(people)); var queryResponse = await db.Query( $"SELECT Marketing, count() AS Count FROM type::table({TABLE}) GROUP BY Marketing" ); var groups = queryResponse.GetValue<List<Group>>(0); Console.WriteLine(ToJsonString(groups)); static string ToJsonString(object? o) { return JsonSerializer.Serialize(o, new JsonSerializerOptions { WriteIndented = true, }); } public class Person : Record { public string? Title { get; set; } public Name? Name { get; set; } public bool Marketing { get; set; } } public class Name { public string? FirstName { get; set; } public string? LastName { get; set; } } public class ResponsibilityMerge : Record { public bool Marketing { get; set; } } public class Group { public bool Marketing { get; set; } public int Count { get; set; } }
Then make sure your SurrealDB server is running on 127.0.0.1:8000
and run your app from the command line with:
dotnet run
The .NET SDK comes with a number of built-in functions.
Function | Description |
---|---|
new SurrealDbClient(endpoint) | Creates a new client, detecting the right protocol from the endpoint |
db.Configure(ns, db, credentials) | Configures the client to use a specific namespace and database, with credentials |
await db.Connect(url, options) | Connects the client to the underlying endpoint, also improving performance to avoid cold starts |
await db.Use(ns, db) | Switch to a specific namespace and database |
await db.Signup(credentials) | Signs up a user to a specific authentication scope |
await db.Signin(credentials) | Signs this connection in to a specific authentication scope |
await db.Authenticate(token) | Authenticates the current connection with a JWT token |
await db.Invalidate() | Invalidates the authentication for the current connection |
await db.Info<T>() | Returns the record of an authenticated scope user |
await db.Set(key, value) | Assigns a value as a parameter for this connection |
await db.Unset(key) | Removes a parameter for this connection |
await db.Query(sql) | Runs a set of SurrealQL statements against the database |
await db.RawQuery(sql, params) | Runs a set of SurrealQL statements against the database, based on a raw SurrealQL query |
await db.Select<T>(resource) | Selects all records in a table, or a specific record |
await db.Create<T>(resource, data) | Creates a record in the database |
await db.Upsert<T>(data) | Creates or updates a specific record |
await db.UpdateAll<T>(table, data) | Updates all records in a table |
await db.Merge<T>(resource, data) | Modifies all records in a table, or a specific record |
await db.MergeAll<T>(table, data) | Modifies all records in a table |
await db.Patch<T>(resource, data) | Applies JSON Patch changes to a specific record |
await db.PatchAll<T>(table, data) | Applies JSON Patch changes to all records in a table |
await db.Delete(resource, data) | Deletes all records, or a specific record |
db.ListenLive<T>(queryUuid) | Listen for live query responses |
await db.LiveQuery<T>(sql) | Initiate a live query from a SurrealQL statement |
await db.LiveRawQuery<T>(sql, params) | Initiate a live query from a SurrealQL statement, based on a raw SurrealQL query |
await db.LiveTable<T>(table, diff) | Initiate a live query from a table |
await db.Kill(queryUuid) | Kill a running live query |
await db.Version() | Retrieves the version of the SurrealDB instance |
await db.Health() | Checks the status of the database server and storage engine |
SurrealDbClient
Creates a new client, detecting the right protocol from the endpoint.
Method Syntaxnew SurrealDbClient(endpoint)
Arguments | Description | ||
---|---|---|---|
endpoint required | The database endpoint to connect to. | ||
httpClientFactory optional | An IHttpClientFactory instance. |
// Creates a new client using a local endpoint var db = new SurrealDbClient("http://127.0.0.1:8000"); // Creates a new client using a remote endpoint var db = new SurrealDbClient("wss://cloud.surrealdb.com");
.Configure()
Configures the client to use a specific namespace and database, with credentials.
Method Syntaxdb.Configure(ns, db, credentials)
Arguments | Description | ||
---|---|---|---|
ns optional | The table namespace to use. | ||
db optional | The table database to use. | ||
username optional | The username with root access. | ||
password optional | The password with root access. | ||
token optional | The value of the JWT token. |
// Configure a connection to use ns/db client.Configure("ns", "db"); // Configure a connection to use ns/db, as well as root access (with username and password) client.Configure("ns", "db", "root", "root"); // Configure a connection to use ns/db, as well as user auth via JWT token string token = "eyJhbGciOiJIUzI1..."; client.Configure("ns", "db", token);
.Connect()
Connects the client to the underlying endpoint, also improving performance to avoid cold starts.
Method Syntaxawait db.Connect()
Arguments | Description | ||
---|---|---|---|
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
await db.Connect();
.Use()
Switch to a specific namespace and database.
Method Syntaxawait db.Use(ns, db)
Arguments | Description | ||
---|---|---|---|
ns initially required | Switches to a specific namespace. | ||
db initially required | Switches to a specific database. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
await db.Use("test", "test");
.SignUp()
Signs up to a specific authentication scope.
Method Syntaxawait db.SignUp(credentials)
Arguments | Description | ||
---|---|---|---|
credentials required | Credentials to sign up as a scoped user. | ||
cancellationToken required | The cancellationToken enables graceful cancellation of asynchronous operations. |
var authParams = new AuthParams { Namespace = "test", Database = "test", Scope = "user", Email = "info@surrealdb.com", Password = "123456" }; Jwt jwt = await db.SignUp(authParams); public class AuthParams : ScopeAuth { public string? Username { get; set; } public string? Email { get; set; } public string? Password { get; set; } }
.SignIn()
Signs in to a specific authentication scope.
Method Syntaxawait db.SignIn(credentials)
Arguments | Description | ||
---|---|---|---|
credentials required | Variables used in a signin query. | ||
cancellationToken required | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Option 1: Sign in as root user await db.SignIn(new RootAuth { Username = "root", Password = "root" }); // Option 2: Sign in using namespace auth await db.SignIn( new NamespaceAuth { Namespace = "test", Username = "johndoe", Password = "password123" } ); // Option 3: Sign in using database auth await db.SignIn( new DatabaseAuth { Namespace = "test", Database = "test", Username = "johndoe", Password = "password123" } ); // Option 4: Sign in as a scoped user var authParams = new AuthParams { Namespace = "test", Database = "test", Scope = "user", Email = "info@surrealdb.com", Password = "123456" }; Jwt jwt = await db.SignIn(authParams); public class AuthParams : ScopeAuth { public string? Username { get; set; } public string? Email { get; set; } public string? Password { get; set; } }
.Authenticate()
Authenticates the current connection with a JWT token.
Method Syntaxawait db.Authenticate(jwt)
Arguments | Description | ||
---|---|---|---|
jwt required | The JWT object holder of the authentication token. | ||
cancellationToken required | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Sign in or sign up as a scoped user Jwt jwt = await db.SignUp(authParams); await db.Authenticate(jwt);
.Invalidate()
Invalidates the authentication for the current connection.
Method Syntaxawait db.Invalidate()
Properties | Description | ||
---|---|---|---|
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
await db.Invalidate();
.Info<T>()
This method returns the record of an authenticated scope user.
Method Syntaxawait db.Info<T>()
Properties | Description | ||
---|---|---|---|
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
var currentUser = await db.Info<User>();
.Set()
Assigns a value as a parameter for this connection.
Method Syntaxawait db.Set(key, val)
Arguments | Description | ||
---|---|---|---|
key required | Specifies the name of the variable. | ||
value required | Assigns the value to the variable name. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Assign the variable on the connection await db.Set("name", new Name { FirstName = "Tobie", LastName = "Morgan Hitchcock" }); // Use the variable in a subsequent query await db.Query($"CREATE person SET name = $name"); // Use the variable in a subsequent query await db.Query($"SELECT * FROM person WHERE name.first_name = $name.first_name");
.Unset()
Removes a parameter for this connection.
Method Syntaxawait db.Unset(key)
Arguments | Description | ||
---|---|---|---|
key required | Specifies the SurrealQL statements. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
await db.Unset("name");
.Query()
Runs a set of SurrealQL statements against the database.
Method Syntaxawait db.Query(sql)
Arguments | Description | ||
---|---|---|---|
sql required | Specifies the SurrealQL statements. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Execute query with params const string table = "person"; var result = await db.Query($"CREATE person; SELECT * FROM type::table({table});"); // Get the first result from the first query var created = result.GetValue<Person>(0); // Get all of the results from the second query var people = result.GetValue<List<Person>>(1);
.RawQuery()
Runs a set of SurrealQL statements against the database, based on a raw SurrealQL query.
Method Syntaxawait db.RawQuery(sql, params)
Arguments | Description | ||
---|---|---|---|
sql required | Specifies the SurrealQL statements. | ||
params optional | Assigns variables which can be used in the query. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Assign the variable on the connection var @params = new Dictionary<string, object> { { "table", "person" } }; var result = await db.RawQuery("CREATE person; SELECT * FROM type::table($table);", @params); // Get the first result from the first query var created = result.GetValue<Person>(0); // Get all of the results from the second query var people = result.GetValue<List<Person>>(1);
.Select<T>()
Selects all records in a table, or a specific record, from the database.
Method Syntaxawait db.Select<T>(resource)
Arguments | Description | ||
---|---|---|---|
resource required | The table name or a record ID to select. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Select all records from a table var people = await db.Select<Person>("person"); // Select a specific record from a table var person = await db.Select<Person>(("person", "h5wxrf2ewk8xjxosxtyc");); // Select a specific record from a table, given a non-string id var person = await db.Select<Person>(("person", new Guid("8424486b-85b3-4448-ac8d-5d51083391c7")));
.Create<T>()
Creates a record in the database.
Method Syntaxawait db.Create<T>(resource, data)
Arguments | Description | ||
---|---|---|---|
resource required | The table name or the specific record ID to create. | ||
data optional | The document / record data to insert. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Create a record with a random ID var person = await db.Create<Person>("person"); // Create a record with a random ID & specific fields var person = await db.Create("person", new Person { Name = "Tobie" }); // Create a record with a specific ID var personToCreate = new Person { Id = ("person", "tobie"), Name = "Tobie", Settings = new Settings { Active = true, Marketing = true, }, }; var result = await db.Create(personToCreate);
.Upsert<T>()
Creates or updates a specific record.
Method Syntaxawait db.Upsert<T>(data)
NoteThis function creates a new document / record or replaces the current one with the specified data.
Arguments | Description | ||
---|---|---|---|
data required | The document / record data to insert. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
var person = new Person { Id = ("person", "tobie"), // Id is mandatory to apply create or update Name = "Tobie", Settings = new Settings { Active = true, Marketing = true, }, }; // Create a new record when it doesn't exist var created = await db.Upsert(person); // Update an existing record when it does exist var updated = await db.Upsert(person);
.UpdateAll<T>()
Updates all records in a table.
Method Syntaxawait db.UpdateAll<T>(table, data)
Arguments | Description | ||
---|---|---|---|
table required | The table name. | ||
data required | The document / record data to update. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
var data = new Person { Name = "Tobie", Settings = new Settings { Active = true, Marketing = true, }, }; await db.UpdateAll("person", data);
.Merge<T>()
Modifies all records in a table, or a specific record.
Method Syntaxawait db.Merge<T>(resource, data)
Arguments | Description | ||
---|---|---|---|
resource required | The specific record ID to modify. | ||
data optional | The data with which to modify the records. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Only changes the fields specified in the merge object var merge = new PersonMerge { Id = ("person", "tobie"), Settings = new Settings { Active = true, Marketing = false, }, }; var result = await db.Merge<PersonMerge, Person>(merge); // Only changes the fields specified in the Dictionary var data = new Dictionary<string, object> { { "tags", new List<string> { "developer", "engineer" } } }; var result = await db.Merge<Person>(("person", "tobie"), data);
.MergeAll<T>()
Modifies all records in a table.
Method Syntaxawait db.MergeAll<T>(table, data)
Arguments | Description | ||
---|---|---|---|
table required | The table name. | ||
data optional | The data with which to modify the records. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Only changes the fields specified in the merge object var merge = new PersonMerge { Settings = new Settings { Active = true, Marketing = false, }, }; var result = await db.MergeAll<PersonMerge, Person>("person", merge); // Only changes the fields specified in the Dictionary var data = new Dictionary<string, object> { { "tags", new List<string> { "developer", "engineer" } } }; var result = await db.MergeAll<Person>("person", data);
.Patch<T>()
Applies JSON Patch changes to a specific record in the database.
Method Syntaxawait db.Patch<T>(resource, data)
NoteThis function patches document / record data with the specified JSON Patch data.
Arguments | Description | ||
---|---|---|---|
resource required | The specific record ID to modify. | ||
data optional | The JSON Patch data with which to patch the records. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
var result = await db.Patch(("person", "tobie"), patches);
.PatchAll<T>()
Applies JSON Patch changes to all records in the database.
Method Syntaxawait db.PatchAll<T>(table, data)
NoteThis function patches document / record data with the specified JSON Patch data.
Arguments | Description | ||
---|---|---|---|
table required | The table name. | ||
data optional | The JSON Patch data with which to patch the records. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
var result = await db.PatchAll("person", patches);
.Delete()
Deletes all records in a table, or a specific record, from the database.
Method Syntaxawait db.Delete(resource)
Arguments | Description | ||
---|---|---|---|
resource required | The table name or a record ID to select. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
// Delete all records from a table await db.Delete("person"); // Delete a specific record from a table await db.Delete(("person", "h5wxrf2ewk8xjxosxtyc"));
.ListenLive<T>()
Listen responses from an existing live query.
Method Syntaxdb.ListenLive<T>(queryUuid)
Arguments | Description | ||
---|---|---|---|
queryUuid required | The UUID of the live query to consume. |
await using var liveQuery = db.ListenLive<Person>(queryUuid); // Option 1 // Consume the live query via an IAsyncEnumerable, // blocking the current thread until the query is killed. await foreach (var response in liveQuery) { // Either a Create, Update, Delete or Close response... } // ------------------------------ // Option 2 // Consume the live query via an Observable. liveQuery .ToObservable() .Subscribe(() => { // Either a Create, Update, Delete or Close response... });
.LiveQuery<T>()
Initiate a live query from a SurrealQL statement.
Method Syntaxawait db.LiveQuery<T>(sql)
Arguments | Description | ||
---|---|---|---|
sql required | Specifies the SurrealQL statements. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
const string table = "person"; await using var liveQuery = await db.LiveQuery<Person>($"LIVE SELECT * FROM type::table({table});"); // Consume the live query...
.LiveRawQuery<T>()
Initiate a live query from a SurrealQL statement, based on a raw SurrealQL query.
Method Syntaxawait db.LiveRawQuery<T>(sql, params)
Arguments | Description | ||
---|---|---|---|
sql required | Specifies the SurrealQL statements. | ||
params optional | Assigns variables which can be used in the query. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
await using var liveQuery = await db.LiveRawQuery<Person>("LIVE SELECT * FROM person;"); // Consume the live query...
.LiveTable<T>()
Initiate a live query from a table.
Method Syntaxawait db.LiveTable<T>(table, diff)
Arguments | Description | ||
---|---|---|---|
table required | The table name to listen for changes for. | ||
diff optional | If set to true, live notifications will include an array of JSON Patch objects, rather than the entire record for each notification. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
await using var liveQuery = await db.LiveTable<Person>("person"); // Consume the live query...
.Kill()
Kills a running live query by it’s UUID.
Method Syntaxawait db.Kill(queryUuid)
Arguments | Description | ||
---|---|---|---|
queryUuid required | The UUID of the live query you wish to kill. | ||
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
await db.Kill(queryUuid);
.Version()
Retrieves the version of the SurrealDB instance.
Method Syntaxawait db.Version()
Arguments | Description | ||
---|---|---|---|
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
string version = await db.Version(); // Will return "surrealdb-1.1.1"
.Health()
Checks the status of the database server and storage engine.
Method Syntaxawait db.Health()
Arguments | Description | ||
---|---|---|---|
cancellationToken optional | The cancellationToken enables graceful cancellation of asynchronous operations. |
bool status = await db.Health();
The .NET SDK also support Dependency Injection to ease the use of the SurrealDbClient
in your application.
Let’s start by creating a new ASP.NET Core web app.
dotnet new webapp -o SurrealDbWeatherApi cd SurrealDbWeatherApi dotnet add package SurrealDb.Net
Open appsettings.Development.json
and replace everything in there with the following code. We have added a new Connection String called SurrealDB
with the default configuration.
{ "AllowedHosts": "*", "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "ConnectionStrings": { "SurrealDB": "Server=http://127.0.0.1:8000;Namespace=test;Database=test;Username=root;Password=root" } }
Open Program.cs
and replace everything in there with the following code. This code is using the AddSurreal()
extension method to inject services automatically. Notice that all we have to do is one line of code to configure the SurrealDB client with the previously set Connection String.
NoteBy default, this function will register both
ISurrealDbClient
andSurrealDbClient
using theSingleton
service lifetime.
var builder = WebApplication.CreateBuilder(args); var services = builder.Services; var configuration = builder.Configuration; services.AddControllers(); services.AddEndpointsApiExplorer(); services.AddSwaggerGen(); services.AddSurreal(configuration.GetConnectionString("SurrealDB")); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
Open WeatherForecastController.cs
and replace everything in there with the following code. Finally, we can inject the ISurrealDbClient
inside our Controller.
using Microsoft.AspNetCore.Mvc; namespace SurrealDbWeatherApi.Controllers; [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private const string Table = "weatherForecast"; private readonly ISurrealDbClient _surrealDbClient; public WeatherForecastController(ISurrealDbClient surrealDbClient) { _surrealDbClient = surrealDbClient; } [HttpGet] [Route("/")] public Task<List<WeatherForecast>> GetAll(CancellationToken cancellationToken) { return _surrealDbClient.Select<WeatherForecast>(Table, cancellationToken); } [HttpPost] [Route("/")] public Task<WeatherForecast> Create(CreateWeatherForecast data, CancellationToken cancellationToken) { var weatherForecast = new WeatherForecast { Date = data.Date, Country = data.Country, TemperatureC = data.TemperatureC, Summary = data.Summary }; return _surrealDbClient.Create(Table, weatherForecast, cancellationToken); } // ... // Other methods omitted for brevity } public class CreateWeatherForecast { public DateTime Date { get; set; } public string? Country { get; set; } public int TemperatureC { get; set; } public string? Summary { get; set; } }
Then make sure your SurrealDB server is running on 127.0.0.1:8000
and run your app from the command line with:
dotnet run
Connection Strings are an easy way to configure your application to connect to a SurrealDB instance. They are stored in the appsettings.json
file and can be used to configure the SurrealDbClient
.
In general, it is known as a best practice to:
appsettings.Development.json
,Keys | Description | Aliases | |
---|---|---|---|
Endpoint required | The database endpoint to connect to. | Server | |
Namespace optional | Switches to a specific namespace. | NS | |
Database optional | Switches to a specific database. | DB | |
Username optional | Username used to have root access. | User | |
Password optional | Password used to have root access. | Pass | |
Token optional | Token (JWT) used to have user access. | ||
NamingPolicy optional | Naming policy used to interact with the database. |
Here is a couple of examples of Connection Strings:
Server=http://127.0.0.1:8000;Namespace=test;Database=test;Username=root;Password=root
Endpoint=http://127.0.0.1:8000;NS=test;DB=test;User=root;Pass=root
Endpoint=http://127.0.0.1:8000;NS=test;DB=test;User=root;Pass=root;NamingPolicy=SnakeCaseLower