The ScalarDB Cluster .NET Client SDK supports the distributed transaction functionality of ScalarDB Cluster. The SDK includes transaction and manager abstractions for easier communication within a cluster.

Note

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

For details about distributed SQL transactions, see Getting Started with Distributed SQL Transactions in the ScalarDB Cluster .NET Client SDK.

Get a transaction manager

First, you need to get a transaction manager for distributed transactions. To get the transaction manager, you can use TransactionFactory as follows, replacing <HOSTNAME_OR_IP_ADDRESS> with the FQDN or the IP address, and <PORT> with the port number (60053 by default) of your cluster:

var scalarDbOptions = new ScalarDbOptions
                      {
                         Address = "http://<HOSTNAME_OR_IP_ADDRESS>:<PORT>",
                         HopLimit = 10
                      };
var factory = TransactionFactory.Create(scalarDbOptions);

using var manager = factory.GetTransactionManager();

Manage transactions

To execute CRUD operations, a transaction is needed. You can begin a transaction by using the transaction manager as follows:

var transaction = await manager.BeginAsync();

You can also resume a transaction that is already being executed as follows:

var transaction = manager.Resume(transactionIdString);

Note

The Resume method doesn’t have an asynchronous version because it only creates a transaction object. Because of this, resuming a transaction by using the wrong ID is possible.

When a transaction is ready to be committed, you can call the CommitAsync method of the transaction as follows:

await transaction.CommitAsync();

To roll back the transaction, you can use the RollbackAsync method:

await transaction.RollbackAsync();

Execute CRUD operations

A transaction has GetAsync, ScanAsync, PutAsync, DeleteAsync, and MutateAsync methods to execute CRUD commands against the cluster. As a parameter, these methods have a command object. A command object can be created by using the builders listed in this section.

To use these builders add the following namespace to the using section:

using ScalarDB.Net.Client.Builders;

Note

The cluster does not support parallel execution of commands inside one transaction, so make sure to use await for asynchronous methods.

GetAsync method example

using GetTypeEnum = Scalar.Db.Cluster.Rpc.V1.Get.Types.GetType;

// ...

var get =
    new GetBuilder()
        .SetNamespaceName("ns")
        .SetTableName("statements")
        .SetGetType(GetTypeEnum.Get)
        .AddPartitionKey("order_id", "1")
        .AddClusteringKey("item_id", 2)
        .SetProjections("item_id", "count")
        .Build();

var getResult = await transaction.GetAsync(get);

ScanAsync method example

using static Scalar.Db.Cluster.Rpc.V1.Scan.Types;

// ..

var scan =
    new ScanBuilder()
        .SetNamespaceName("ns")
        .SetTableName("statements")
        .SetScanType(ScanType.Scan)
        .AddPartitionKey("order_id", "1")
        .AddStartClusteringKey("item_id", 2)
        .SetStartInclusive(true)
        .AddEndClusteringKey("item_id", 8)
        .SetEndInclusive(true)
        .SetProjections("item_id", "count")
        .Build();

var scanResult = await transaction.ScanAsync(get);

PutAsync method example

var put =
    new PutBuilder()
        .SetNamespaceName("ns")
        .SetTableName("statements")
        .AddPartitionKey("order_id", "1")
        .AddClusteringKey("item_id", 2)
        .AddColumn("count", 11)
        .Build();

await client.PutAsync(put);

DeleteAsync method example

var delete =
    new DeleteBuilder()
        .SetNamespaceName("ns")
        .SetTableName("statements")
        .AddPartitionKey("order_id", "1")
        .AddClusteringKey("item_id", 2)
        .Build();

await client.DeleteAsync(delete);

MutateAsync method example:

using Scalar.Db.Cluster.Rpc.V1;

// ...

var put =
    new PutBuilder()
        .SetNamespaceName("ns")
        .SetTableName("statements")
        .AddPartitionKey("order_id", "1")
        .AddClusteringKey("item_id", 2)
        .AddColumn("count", 11)
        .Build();

var mutate = new Mutation { Put = put };

await client.MutateAsync(new[] { mutate });

Note

To modify data by using the PutAsync, DeleteAsync, or MutateAsync method, the data must be retrieved first by using the GetAsync or ScanAsync method.