Data Types
The .NET SDK translates datatypes native to SurrealQL into either datatypes native to .NET, or a custom implementation. This document describes all datatypes, and links to their respective documentation.
Data Types overview
None
The None type is a custom type that represents the absence of a value.
Signature
public readonly struct None { }
Working with None
Constructing
var none = new None();
var myRecord = new MyRecord();
myRecord.Value = new None();
RecordId
When you receive a RecordId back from SurrealDB, it will always be represented as a RecordId. The class holds Table and Id fields, representing the table name, and a unique identifier for the record on that table.
Signature
public class RecordId
{
public string Table { get; }
public T DeserializeId<T>();
}
The RecordId is a non-generic class, allowing you to extract the Id field by providing the output type via the DeserializeId method. This can helpful when the RecordId is used in a generic context, for when you store the Id as an Object or an Array for example.
For cases where you are aware of the type of the Id field, you can use the generic version of RecordId to avoid the need for manual deserialization.
Signature with generics
public class RecordIdOf<T> : RecordId
{
public T Id { get; }
}
The default type of an Id in SurrealDB being a string, you can choose to use the default provided type RecordIdOfString.
Default RecordId
public class RecordIdOfString : RecordIdOf<string>
{
public string Table { get; }
public string Id { get; }
}
Working with RecordId
The simplest and most common way to construct a RecordId is with a tuple (table, id).
Constructing
RecordId personId = ("person", "john");
var personId = (RecordId)("person", "john");
This tuple is implicitly converted into a RecordId object. You can use it with all SDK methods:
Using RecordId
await db.Select<Person>(("person", "john"));
await db.Delete(("person", "john"));
You are not exclusively limited to the string type for the Id part. Several overloads exist for different id types:
Constructing
RecordId rid1 = ("person", "alice");
RecordId rid2 = ("person", 123);
RecordId rid3 = ("person", 123L);
RecordId rid4 = ("person", (short)5);
RecordId rid5 = ("person", (byte)7);
RecordId rid6 = ("person", Guid.NewGuid());
The .NET SDK handles serialization and deserialization of the Table and Id parts in Record Id. The serialization is done automatically when sending data to the server. However, deserialization may need to be done manually according to the data type of the Id field. Below are some examples:
Simple record id
RecordId rid = ("person", "john");
string table = rid.Table;
string id = rid.DeserializeId<string>();
Record id with simple data type (other than string)
RecordId rid = ("table", 42);
string table = rid.Table;
int id = rid.DeserializeId<int>();
Record id with complex data types
var rid = new RecordIdOf<CityId>("table", new CityId { City = "London" });
var id = rid.DeserializeId<CityId>();
var rid = new RecordIdOf<(string, int)>("table", ("London", 42));
var id = rid.DeserializeId<(string, int)>();
Send back string
If you need to send back a Record Id in string format, you can do so with the StringRecordId class.
We do not implement the parsing of Record Ids in the .NET SDK, as that would mean that we need to be able to parse any SurrealQL value, which comes with a cost. Instead you can send it over as a string with StringRecordId, allowing the server to handle the parsing.
Signature
public class StringRecordId
{
public string Value { get; }
}
Working with a StringRecordId
Constructing
var rid = new StringRecordId("person:john");
var rid = (StringRecordId)"person:john";
await client.Select<Person>((StringRecordId)"person:john");
Working with RecordIdOfString
For string-based identifiers, you can also use the specialized type RecordIdOfString:
Using RecordIdOfString
var rid = new RecordIdOfString("person", "john");
Console.WriteLine(rid.Table);
Console.WriteLine(rid.Id);
Working with RecordIdOf<T>
For complex or structured identifiers, use the generic type RecordIdOf<T>:
Using RecordIdOf<T>
public class CityId
{
public string City { get; set; } = string.Empty;
}
var rid = new RecordIdOf<CityId>("city", new CityId { City = "London" });
This enables strongly-typed IDs that map directly to your domain objects.
Inheriting from Record
If your model class inherits from Record, it will automatically include an Id property of type RecordId.
Inheriting from Record
public class Person : Record
{
public string Name { get; set; } = string.Empty;
}
var person = new Person { Name = "Alice" };
Console.WriteLine(person.Id);
Using Data Annotations
The SDK supports attributes for serialization and deserialization.
CBOR serialization
Use CborProperty to map C# properties to SurrealDB fields:
Using CborProperty
[CborProperty("first_name")]
public string FirstName { get; set; } = string.Empty;
RecordIdJsonConverter
Use RecordIdJsonConverter to indicate that a property should be serialized as a RecordId reference to another table:
Using RecordIdJsonConverter
[RecordIdJsonConverter("payment_details")]
public RecordId? PaymentDetails { get; set; }
[RecordIdJsonConverter("payment_details")]
public RecordId? PaymentDetails { get; set; }
Combining attributes
You can combine both attributes on the same property:
Combining attributes
[CborProperty("payment_details")]
[RecordIdJsonConverter("payment_details")]
public RecordId? PaymentDetails { get; set; }