C# Native API
C# Native API
1. Feature Overview
IoTDB provides a C# native client driver and corresponding connection pool, offering object-oriented interfaces that allow direct assembly of time-series objects for writing without SQL construction. It is recommended to use the connection pool for multi-threaded parallel database operations.
2. Usage Instructions
Environment Requirements:
- .NET SDK >= 5.0 or .NET Framework 4.x
- Thrift >= 0.14.1
- NLog >= 4.7.9
Dependency Installation:
It supports installation using tools such as NuGet Package Manager or .NET CLI. Taking .NET CLI as an example:
If using .NET 5.0 or a later version of the SDK, enter the following command to install the latest NuGet package:
dotnet add package Apache.IoTDB
3. Read/Write Operations
3.1 TableSessionPool
3.1.1 Functional Description
The TableSessionPool
defines basic operations for interacting with IoTDB, supporting data insertion, query execution, and session closure. It also serves as a connection pool to efficiently reuse connections and properly release resources when unused. This interface defines how to acquire sessions from the pool and how to close the pool.
3.1.2 Method List
Below are the methods defined in TableSessionPool
with detailed descriptions:
Method | Description | Parameters | Return Type |
---|---|---|---|
Open(bool enableRpcCompression) | Opens a session connection with custom enableRpcCompression | enableRpcCompression : Whether to enable RpcCompression (requires server-side configuration alignment) | Task |
Open() | Opens a session connection without enabling RpcCompression | None | Task |
InsertAsync(Tablet tablet) | Inserts a Tablet object containing time-series data into the database | tablet : The Tablet object to insert | Task<int> |
ExecuteNonQueryStatementAsync(string sql) | Executes a non-query SQL statement (e.g., DDL/DML commands) | sql : The SQL statement to execute | Task<int> |
ExecuteQueryStatementAsync(string sql) | Executes a query SQL statement and returns a SessionDataSet with results | sql : The SQL query to execute | Task<SessionDataSet> |
ExecuteQueryStatementAsync(string sql, long timeoutInMs) | Executes a query SQL statement with a timeout (milliseconds) | sql : The SQL query to execute timeoutInMs : Query timeout in milliseconds | Task<SessionDataSet> |
Close() | Closes the session and releases held resources | None | Task |
3.1.3 Interface Examples
public async Task Open(bool enableRpcCompression, CancellationToken cancellationToken = default)
public async Task Open(CancellationToken cancellationToken = default)
public async Task<int> InsertAsync(Tablet tablet)
public async Task<int> ExecuteNonQueryStatementAsync(string sql)
public async Task<SessionDataSet> ExecuteQueryStatementAsync(string sql)
public async Task<SessionDataSet> ExecuteQueryStatementAsync(string sql, long timeoutInMs)
public async Task Close()
3.2 TableSessionPool.Builder
3.2.1 Functional Description
The TableSessionPool.Builder
class configures and creates instances of TableSessionPool
, allowing developers to set connection parameters, session settings, and pooling behaviors.
3.2.2 Configuration Options
Below are the available configuration options for TableSessionPool.Builder
and their defaults:
Configuration Method | Description | Default Value |
---|---|---|
SetHost(string host) | Sets the IoTDB node host | localhost |
SetPort(int port) | Sets the IoTDB node port | 6667 |
SetNodeUrls(List nodeUrls) | Sets IoTDB cluster node URLs (overrides SetHost /SetPort when used) | Not set |
SetUsername(string username) | Sets the connection username | "root" |
SetPassword(string password) | Sets the connection password | "root" |
SetFetchSize(int fetchSize) | Sets the fetch size for query results | 1024 |
SetZoneId(string zoneId) | Sets the timezone ZoneID | UTC+08:00 |
SetPoolSize(int poolSize) | Sets the maximum number of sessions in the connection pool | 8 |
SetEnableRpcCompression(bool enable) | Enables/disables RPC compression | false |
SetConnectionTimeoutInMs(int timeout) | Sets the connection timeout in milliseconds | 500 |
SetDatabase(string database) | Sets the target database name | "" |
3.2.3 Interface Examples
public Builder SetHost(string host)
{
_host = host;
return this;
}
public Builder SetPort(int port)
{
_port = port;
return this;
}
public Builder SetUsername(string username)
{
_username = username;
return this;
}
public Builder SetPassword(string password)
{
_password = password;
return this;
}
public Builder SetFetchSize(int fetchSize)
{
_fetchSize = fetchSize;
return this;
}
public Builder SetZoneId(string zoneId)
{
_zoneId = zoneId;
return this;
}
public Builder SetPoolSize(int poolSize)
{
_poolSize = poolSize;
return this;
}
public Builder SetEnableRpcCompression(bool enableRpcCompression)
{
_enableRpcCompression = enableRpcCompression;
return this;
}
public Builder SetConnectionTimeoutInMs(int timeout)
{
_connectionTimeoutInMs = timeout;
return this;
}
public Builder SetNodeUrls(List<string> nodeUrls)
{
_nodeUrls = nodeUrls;
return this;
}
protected internal Builder SetSqlDialect(string sqlDialect)
{
_sqlDialect = sqlDialect;
return this;
}
public Builder SetDatabase(string database)
{
_database = database;
return this;
}
public Builder()
{
_host = "localhost";
_port = 6667;
_username = "root";
_password = "root";
_fetchSize = 1024;
_zoneId = "UTC+08:00";
_poolSize = 8;
_enableRpcCompression = false;
_connectionTimeoutInMs = 500;
_sqlDialect = IoTDBConstant.TABLE_SQL_DIALECT;
_database = "";
}
public TableSessionPool Build()
{
SessionPool sessionPool;
// if nodeUrls is not empty, use nodeUrls to create session pool
if (_nodeUrls.Count > 0)
{
sessionPool = new SessionPool(_nodeUrls, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database);
}
else
{
sessionPool = new SessionPool(_host, _port, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database);
}
return new TableSessionPool(sessionPool);
}
4. Example
Complete example : samples/Apache.IoTDB.Samples/TableSessionPoolTest.cs
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Apache.IoTDB.DataStructure;
namespace Apache.IoTDB.Samples;
public class TableSessionPoolTest
{
private readonly SessionPoolTest sessionPoolTest;
public TableSessionPoolTest(SessionPoolTest sessionPoolTest)
{
this.sessionPoolTest = sessionPoolTest;
}
public async Task Test()
{
await TestCleanup();
await TestSelectAndInsert();
await TestUseDatabase();
// await TestCleanup();
}
public async Task TestSelectAndInsert()
{
var tableSessionPool = new TableSessionPool.Builder()
.SetNodeUrls(sessionPoolTest.nodeUrls)
.SetUsername(sessionPoolTest.username)
.SetPassword(sessionPoolTest.password)
.SetFetchSize(1024)
.Build();
await tableSessionPool.Open(false);
if (sessionPoolTest.debug) tableSessionPool.OpenDebugMode();
await tableSessionPool.ExecuteNonQueryStatementAsync("CREATE DATABASE test1");
await tableSessionPool.ExecuteNonQueryStatementAsync("CREATE DATABASE test2");
await tableSessionPool.ExecuteNonQueryStatementAsync("use test2");
// or use full qualified table name
await tableSessionPool.ExecuteNonQueryStatementAsync(
"create table test1.table1(region_id STRING TAG, plant_id STRING TAG, device_id STRING TAG, model STRING ATTRIBUTE, temperature FLOAT FIELD, humidity DOUBLE FIELD) with (TTL=3600000)");
await tableSessionPool.ExecuteNonQueryStatementAsync(
"create table table2(region_id STRING TAG, plant_id STRING TAG, color STRING ATTRIBUTE, temperature FLOAT FIELD, speed DOUBLE FIELD) with (TTL=6600000)");
// show tables from current database
var res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES");
res.ShowTableNames();
while (res.HasNext()) Console.WriteLine(res.Next());
await res.Close();
// show tables by specifying another database
// using SHOW tables FROM
res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES FROM test1");
res.ShowTableNames();
while (res.HasNext()) Console.WriteLine(res.Next());
await res.Close();
var tableName = "testTable1";
List<string> columnNames =
new List<string> {
"region_id",
"plant_id",
"device_id",
"model",
"temperature",
"humidity" };
List<TSDataType> dataTypes =
new List<TSDataType>{
TSDataType.STRING,
TSDataType.STRING,
TSDataType.STRING,
TSDataType.STRING,
TSDataType.FLOAT,
TSDataType.DOUBLE};
List<ColumnCategory> columnCategories =
new List<ColumnCategory>{
ColumnCategory.TAG,
ColumnCategory.TAG,
ColumnCategory.TAG,
ColumnCategory.ATTRIBUTE,
ColumnCategory.FIELD,
ColumnCategory.FIELD};
var values = new List<List<object>> { };
var timestamps = new List<long> { };
for (long timestamp = 0; timestamp < 100; timestamp++)
{
timestamps.Add(timestamp);
values.Add(new List<object> { "1", "5", "3", "A", 1.23F + timestamp, 111.1 + timestamp });
}
var tablet = new Tablet(tableName, columnNames, columnCategories, dataTypes, values, timestamps);
await tableSessionPool.InsertAsync(tablet);
res = await tableSessionPool.ExecuteQueryStatementAsync("select * from testTable1 "
+ "where region_id = '1' and plant_id in ('3', '5') and device_id = '3'");
res.ShowTableNames();
while (res.HasNext()) Console.WriteLine(res.Next());
await res.Close();
await tableSessionPool.Close();
}
public async Task TestUseDatabase()
{
var tableSessionPool = new TableSessionPool.Builder()
.SetNodeUrls(sessionPoolTest.nodeUrls)
.SetUsername(sessionPoolTest.username)
.SetPassword(sessionPoolTest.password)
.SetDatabase("test1")
.SetFetchSize(1024)
.Build();
await tableSessionPool.Open(false);
if (sessionPoolTest.debug) tableSessionPool.OpenDebugMode();
// show tables from current database
var res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES");
res.ShowTableNames();
while (res.HasNext()) Console.WriteLine(res.Next());
await res.Close();
await tableSessionPool.ExecuteNonQueryStatementAsync("use test2");
// show tables from current database
res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES");
res.ShowTableNames();
while (res.HasNext()) Console.WriteLine(res.Next());
await res.Close();
await tableSessionPool.Close();
}
public async Task TestCleanup()
{
var tableSessionPool = new TableSessionPool.Builder()
.SetNodeUrls(sessionPoolTest.nodeUrls)
.SetUsername(sessionPoolTest.username)
.SetPassword(sessionPoolTest.password)
.SetFetchSize(1024)
.Build();
await tableSessionPool.Open(false);
if (sessionPoolTest.debug) tableSessionPool.OpenDebugMode();
await tableSessionPool.ExecuteNonQueryStatementAsync("drop database test1");
await tableSessionPool.ExecuteNonQueryStatementAsync("drop database test2");
await tableSessionPool.Close();
}
}