Skip to main content
Version: 3.14

Getting Started with Tables as C# Classes in the ScalarDB Cluster .NET Client SDK

The ScalarDB Cluster .NET Client SDK helps you write code to access a cluster by abstracting ScalarDB tables as C# objects. After defining a class that represents a table in the cluster, you can ensure that a column name or its type won't be mixed up when querying the cluster. In addition, if a table's structure changes, you can apply the changes to the code by using the refactoring feature in your IDE.

note

Although we recommend using asynchronous methods, as in the following examples, you can use synchronous methods instead.

Install the SDK

Install the same major and minor version of the SDK as ScalarDB Cluster into the .NET project. You can do this by using the built-in NuGet package manager, replacing <MAJOR>.<MINOR> with the version that you're using:

dotnet add package ScalarDB.Client --version '<MAJOR>.<MINOR>.*'

Create classes for all ScalarDB tables

To work with ScalarDB tables as C# objects, you must create a class for each table that you want to use. For example:

using System.ComponentModel.DataAnnotations.Schema;
using ScalarDB.Client.DataAnnotations;

// ...

[Table("ns.statements")]
public class Statement
{
[PartitionKey]
[Column("order_id", Order = 0)]
public string OrderId { get; set; } = String.Empty;

[ClusteringKey]
[Column("item_id", Order = 1)]
public int ItemId { get; set; }

[Column("count", Order = 2)]
public int Count { get; set; }
}

For details about which types should be used for properties, see How ScalarDB Column Types Are Converted to and from .NET Types.

Execute CRUD operations

After creating a class for each table, you can use the classes as objects by using the generic GetAsync, ScanAsync, InsertAsync, UpdateAsync, DeleteAsync, UpsertAsync, or MutateAsync method of ITransactionCrudOperable.

To use these generic methods, add the following namespace to the using section:

using ScalarDB.Client.Extensions;

Get one object by using the GetAsync method

var keys = new Dictionary<string, object>
{
{ nameof(Statement.OrderId), "1" }
};
var statement = await transaction.GetAsync<Statement>(keys);

Console.WriteLine($"ItemId: {statement.ItemId}, Count: {statement.Count}");

Get multiple objects by using the ScanAsync method

var startKeys = new Dictionary<string, object>
{
{ nameof(Statement.OrderId), "1" },
{ nameof(Statement.ItemId), 3 }
};
var endKeys = new Dictionary<string, object>
{
{ nameof(Statement.ItemId), 6}
};

await foreach (var s in transaction.ScanAsync<Statement>(startKeys, endKeys))
Console.WriteLine($"ItemId: {s.ItemId}, Count: {s.Count}");
note

To use LINQ methods with IAsyncEnumerable<T>, you can install System.Linq.Async package.

Insert a new object by using the InsertAsync method

var statement = new Statement
{
OrderId = "2",
ItemId = 4,
Count = 8
};
await transaction.InsertAsync(statement);

Update an object by using the UpdateAsync method

// ...
statement.ItemId = 4;
statement.Count = 8;

await transaction.UpdateAsync(statement);

Delete an object by using the DeleteAsync method

// ...
await transaction.DeleteAsync(statement);

Upsert an object by using the UpsertAsync method

var statement = new Statement
{
OrderId = "2",
ItemId = 4,
Count = 8
};
await transaction.UpsertAsync(statement);

Upsert and delete multiple objects at once by using the MutateAsync method

var statement = new Statement
{
OrderId = "2",
ItemId = 4,
Count = 16
};

// ...

await transaction.MutateAsync(objectsToUpsert: new[] { statement },
objectsToDelete: new[] { statement2 });
note

To modify objects by using the UpdateAsync, DeleteAsync, UpsertAsync, or MutateAsync method, the objects must be retrieved first by using the GetAsync or ScanAsync method.

Use the Administrative API

C# objects also can be used with the Administrative API. To use generic Administrative API methods, add the following namespace to the using section:

using ScalarDB.Client.Extensions;

Create a new namespace

await admin.CreateNamespaceAsync<Statement>();

Drop an existing namespace

await admin.DropNamespaceAsync<Statement>();

Check if a namespace exists

var namespaceExists = await admin.IsNamespacePresentAsync<Statement>();

Create a new table

await admin.CreateTableAsync<Statement>();

Drop an existing table

await admin.DropTableAsync<Statement>();

Check if a table exists

var tableExists = await admin.IsTablePresentAsync<Statement>();