blob: 00f9b5d13985369717b36235ebb3ced9cf1601c1 [file] [log] [blame] [view]
<!--
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.
-->
# C# 原生接口
## 1. 功能介绍
IoTDB具备C#原生客户端驱动和对应的连接池,提供对象化接口,可以直接组装时序对象进行写入,无需拼装 SQL。推荐使用连接池,多线程并行操作数据库。
## 2. 使用方式
**环境要求:**
* .NET SDK >= 5.0 或 .NET Framework 4.x
* Thrift >= 0.14.1
* NLog >= 4.7.9
**依赖安装:**
支持使用 NuGet Package Manager, .NET CLI等工具来安装,以 .NET CLI为例
如果使用的是\\.NET 5.0 或者更高版本的SDK,输入如下命令即可安装最新的NuGet包
```Plain
dotnet add package Apache.IoTDB
```
## 3. 读写操作
### 3.1 TableSessionPool
#### 3.1.1 功能描述
TableSessionPool 定义了与IoTDB交互的基本操作,可以执行数据插入、查询操作以及关闭会话等,同时也是一个连接池这个池可以帮助我们高效地重用连接,并且在不需要时正确地清理资源, 该接口定义了如何从池中获取会话以及如何关闭池的基本操作。
#### 3.1.2 方法列表
以下是 TableSessionPool 中定义的方法及其详细说明:
| 方法 | 描述 | 参数 | 返回值 |
| ---------------------------------------------------------------- | ---------------------------------------------------------------- |-------------------------------------------------------------------|--------------------|
| `Open(bool enableRpcCompression)` | 打开会话连接,自定义`enableRpcCompression` | `enableRpcCompression`:是否启用`RpcCompression`,此参数需配合 Server 端配置一同使用 | `Task` |
| `Open()` | 打开会话连接,不开启`RpcCompression` | 无 | `Task` |
| `InsertAsync(Tablet tablet)` | 将一个包含时间序列数据的Tablet 对象插入到数据库中 | tablet: 要插入的Tablet对象 | `Task<int>` |
| `ExecuteNonQueryStatementAsync(string sql)` | 执行非查询SQL语句,如DDL(数据定义语言)或DML(数据操作语言)命令 | sql: 要执行的SQL语句。 | `Task<int>` |
| `ExecuteQueryStatementAsync(string sql)` | 执行查询SQL语句,并返回包含查询结果的SessionDataSet对象 | sql: 要执行的SQL语句。 | `Task<SessionDataSet>` |
| `ExecuteQueryStatementAsync(string sql, long timeoutInMs)` | 执行查询SQL语句,并设置查询超时时间(以毫秒为单位) | sql: 要执行的查询SQL语句。<br>timeoutInMs: 查询超时时间(毫秒) | `Task<SessionDataSet>` |
| `Close()` | 关闭会话,释放所持有的资源 | 无 | `Task` |
#### 3.1.3 接口展示
```C#
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 功能描述
TableSessionPool.Builder 是 TableSessionPool的构造器,用于配置和创建 TableSessionPool 的实例。允许开发者配置连接参数、会话参数和池化行为等。
#### 3.2.2 配置选项
以下是 TableSessionPool.Builder 类的可用配置选项及其默认值:
| **配置项** | **描述** | **默认值** |
| ---------------------------------------------------- | ---------------------------------------------------------------- |---------------------|
| `SetHost(string host)` | 设置IoTDB的节点 host | `localhost` |
| `SetPort(int port)` | 设置IoTDB的节点端口 | `6667` |
| `SetNodeUrls(List nodeUrls)` | 设置IoTDB集群的节点URL列表,当设置此项时会忽略SetHost和SetPort | `无 ` |
| `SetUsername(string username)` | 设置连接的用户名 | `"root"` |
| `SetPassword(string password)` | 设置连接的密码 | `"TimechoDB@2021"` //V2.0.6.x 之前默认密码是root |
| `SetFetchSize(int fetchSize)` | 设置查询结果的获取大小 | `1024 ` |
| `SetZoneId(string zoneId)` | 设置时区相关的ZoneId | `UTC+08:00` |
| `SetPoolSize(int poolSize)` | 设置会话池的最大大小,即池中允许的最大会话数 | `8 ` |
| `SetEnableRpcCompression(bool enableRpcCompression)` | 是否启用RPC压缩 | `false` |
| `SetConnectionTimeoutInMs(int timeout)` | 设置连接超时时间(毫秒) | `500` |
| `SetDatabase(string database)` | 设置目标数据库名称 | ` "" ` |
#### 3.2.3 接口展示
```c#
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 = "TimechoDB@2021"; //V2.0.6.x 之前默认密码是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. 示例代码
完整示例:[samples/Apache.IoTDB.Samples/TableSessionPoolTest.cs](https://github.com/apache/iotdb-client-csharp/blob/main/samples/Apache.IoTDB.Samples/TableSessionPoolTest.cs)
```c#
/*
* 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();
}
}
```