分类 :11.客户端与连接器 | 篇章 :06 Node.js/C# 连接器
Node.js 适合后端 Web 服务与 IoT 网关,C# 适合 .NET 企业应用与 Windows 工业环境。本文统一讲解两者用法。
速查表
| 维度 | Node.js | C# |
|---|---|---|
| 包名 | @tdengine/websocket | TDengine.Connector |
| 协议 | WebSocket / REST | Native / WebSocket / REST |
| 异步 | async/await | async/await |
| ORM | TypeORM 等(视支持) | EF Core(视支持) |
Node.js 连接器详解
1. 安装
bash
# WebSocket(推荐)
npm install @tdengine/websocket
# REST
npm install @tdengine/rest
2. 基本用法
javascript
const taos = require("@tdengine/websocket");
async function main() {
const conn = await taos.sqlConnect({
url: "ws://localhost:6041",
user: "root",
password: "taosdata",
db: "test"
});
// DDL
await conn.exec("CREATE DATABASE IF NOT EXISTS test");
await conn.exec("USE test");
await conn.exec(`
CREATE STABLE IF NOT EXISTS meters (
ts TIMESTAMP, current FLOAT, voltage INT
) TAGS (location VARCHAR(32))
`);
// INSERT
await conn.exec(`
INSERT INTO d001 USING meters TAGS('Beijing')
VALUES (NOW, 25.3, 220)
`);
// SELECT
const result = await conn.query("SELECT * FROM meters LIMIT 10");
const meta = result.getMeta();
console.log("Columns:", meta);
while (await result.next()) {
const row = result.getData();
console.log(row);
}
await conn.close();
}
main().catch(console.error);
3. STMT2 高性能写入
javascript
const stmt = await conn.statement();
await stmt.prepare("INSERT INTO ? USING meters TAGS(?) VALUES(?, ?, ?)");
// 多子表绑定
const tables = ["d001", "d002"];
const tags = [["Beijing"], ["Shanghai"]];
const data = [
// d001 的数据
{
ts: [Date.now(), Date.now() + 1000],
current: [25.3, 25.8],
voltage: [220, 221]
},
// d002 的数据
{
ts: [Date.now(), Date.now() + 1000],
current: [26.5, 27.1],
voltage: [218, 219]
}
];
for (let i = 0; i < tables.length; i++) {
stmt.setTableName(tables[i]);
stmt.setTags(tags[i]);
stmt.bindParam(data[i]);
}
await stmt.execute();
await stmt.close();
4. TMQ 订阅
javascript
const { TMQConsumer } = require("@tdengine/websocket");
const consumer = new TMQConsumer({
url: "ws://localhost:6041",
user: "root",
password: "taosdata",
"group.id": "my_group",
"auto.offset.reset": "earliest"
});
await consumer.subscribe(["my_topic"]);
while (true) {
const messages = await consumer.poll(1000);
for (const msg of messages) {
console.log(msg);
}
await consumer.commit();
}
5. Express 集成示例
javascript
const express = require("express");
const taos = require("@tdengine/websocket");
const app = express();
app.use(express.json());
let conn;
app.listen(3000, async () => {
conn = await taos.sqlConnect({
url: "ws://localhost:6041",
user: "root",
password: "taosdata",
db: "iot"
});
console.log("Server started on 3000");
});
app.get("/api/devices/:id/recent", async (req, res) => {
const result = await conn.query(
`SELECT * FROM ${req.params.id} WHERE ts > NOW - 1h LIMIT 100`
);
const rows = [];
while (await result.next()) {
rows.push(result.getData());
}
res.json(rows);
});
app.post("/api/devices/:id", async (req, res) => {
const { current, voltage } = req.body;
await conn.exec(
`INSERT INTO ${req.params.id} VALUES (NOW, ${current}, ${voltage})`
);
res.status(201).json({ ok: true });
});
C# 连接器详解
6. 安装
bash
# .NET CLI
dotnet add package TDengine.Connector
7. 基本用法
csharp
using TDengine.Driver;
using TDengine.Driver.Client;
class Program
{
static void Main()
{
// WebSocket
var builder = new ConnectionStringBuilder(
"protocol=WebSocket;host=localhost;port=6041;" +
"user=root;password=taosdata;db=test"
);
using var client = DbDriver.Open(builder);
// DDL
client.Exec("CREATE DATABASE IF NOT EXISTS test");
client.Exec("USE test");
client.Exec(@"
CREATE STABLE IF NOT EXISTS meters (
ts TIMESTAMP, current FLOAT, voltage INT
) TAGS (location VARCHAR(32))
");
// INSERT
client.Exec(
"INSERT INTO d001 USING meters TAGS('Beijing') " +
"VALUES (NOW, 25.3, 220)"
);
// SELECT
using var rows = client.Query("SELECT * FROM meters LIMIT 10");
while (rows.Read())
{
for (int i = 0; i < rows.FieldCount; i++)
{
Console.Write(rows.GetValue(i) + " ");
}
Console.WriteLine();
}
}
}
8. STMT2 与订阅
csharp
// STMT2
using var stmt = client.StmtInit();
stmt.Prepare("INSERT INTO ? USING meters TAGS(?) VALUES(?, ?, ?)");
stmt.SetTableName("d001");
stmt.SetTags(new object[] { "Beijing" });
// 批量数据
var tsArr = new long[1000];
var currentArr = new float[1000];
var voltageArr = new int[1000];
for (int i = 0; i < 1000; i++)
{
tsArr[i] = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + i;
currentArr[i] = 25.0f + i * 0.01f;
voltageArr[i] = 220;
}
stmt.BindColumn(0, tsArr);
stmt.BindColumn(1, currentArr);
stmt.BindColumn(2, voltageArr);
stmt.AddBatch();
stmt.Execute();
// TMQ
using TDengine.TMQ;
var consumerConfig = new Dictionary<string, string>
{
{ "td.connect.ip", "localhost" },
{ "td.connect.user", "root" },
{ "td.connect.pass", "taosdata" },
{ "group.id", "my_group" },
{ "auto.offset.reset", "earliest" }
};
using var consumer = new ConsumerBuilder<Dictionary<string, object>>(
consumerConfig).Build();
consumer.Subscribe(new[] { "my_topic" });
while (true)
{
var cr = consumer.Consume(1000);
if (cr == null) continue;
Console.WriteLine(cr.Message.Value);
consumer.Commit(cr);
}
代码示例
Node.js IoT 网关
javascript
const mqtt = require("mqtt");
const taos = require("@tdengine/websocket");
const tdConn = await taos.sqlConnect({
url: "ws://localhost:6041",
user: "root",
password: "taosdata",
db: "iot"
});
const mqttClient = mqtt.connect("mqtt://broker:1883");
mqttClient.subscribe("sensors/+/data");
const buffer = [];
const FLUSH_INTERVAL = 1000;
const FLUSH_SIZE = 1000;
mqttClient.on("message", (topic, msg) => {
const device = topic.split("/")[1];
const data = JSON.parse(msg);
buffer.push({ device, ...data });
if (buffer.length >= FLUSH_SIZE) {
flush();
}
});
setInterval(flush, FLUSH_INTERVAL);
async function flush() {
if (buffer.length === 0) return;
const batch = buffer.splice(0, buffer.length);
// 批量写入(用 STMT2 性能更好)
for (const item of batch) {
await tdConn.exec(
`INSERT INTO ${item.device} VALUES ` +
`(${item.ts}, ${item.value}, ${item.status})`
);
}
}
C# Windows 服务
csharp
public class IoTService : BackgroundService
{
private readonly ITaosClient _client;
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var data = await ReadFromPLC();
_client.Exec($"INSERT INTO {data.Device} VALUES " +
$"(NOW, {data.Value})");
await Task.Delay(1000, stoppingToken);
}
}
}
性能考量
性能对比
| 操作 | Node.js | C# |
|---|---|---|
| 单条 exec | 几千/秒 | 上万/秒 |
| 批量 STMT2 | 几十万行/秒 | 上百万行/秒 |
| 异步并发 | 高 | 高 |
| 内存占用 | 中 | 低 |
最佳实践
| 语言 | 建议 |
|---|---|
| Node.js | 长连接 + 批量缓冲 |
| C# | using 显式释放 |
| 两者 | 用 STMT2 替代单条 INSERT |
FAQ
Q1: Node.js 浏览器能用吗?
@tdengine/websocket 只能服务端 Node.js。浏览器需用 @tdengine/rest 或自行 WS 实现。
Q2: TypeScript 支持?
两个包都自带 .d.ts 类型定义。
Q3: C# .NET Framework vs Core?
支持 .NET Standard 2.0+,可在 .NET Framework 4.6.1+ 和 .NET Core / .NET 5+ 使用。
Q4: EF Core 集成?
官方暂无 EF Core Provider,需直接用 ADO.NET 接口或自定义 Provider。
Q5: Windows 部署注意?
- Native 需 taos.dll
- WebSocket 无依赖
- 防火墙开放 6041
参考
系统构架篇
- 01-《TDengine 整体架构全景》
- 02-《集群拓扑深度解析》
- 03-《MNode 内部机制深度解析》
- 04-《RPC 通信层深度解析》
- 05-《VNode 生命周期》
- 06-《RAFT 共识协议》
- 07-《端到端的消息流》
数据模型
- 01-《数据库创建与参数详解》
- 02-《超级表/子表/普通表》
- 03-《支持数据类型深度解析》
- 04-《TDengine Tag 设计哲学与 Schema 变更机制》
- 05-《TDengine 虚拟表实现原理》
存储引擎
- 01-《TDengine 存储引擎概览》
- 02-《TDengine MemTable 深度解析》
- 03-《TDengine WAL 预写日志机制》
- 04-《TDengine 数据文件格式》
- 05-《TDengine Commit 与 Flush 机制 》
- 06-《TDengine Compaction 合并策略 》
- 07-《TDengine 数据保留与 TTL》
- 08-《TDengine 压缩编码机制》
- 09-《TDengine Cache 与 Last 查询加速》
- 10-《TDengine 逻辑计划生成》
查询引擎
- 01-《TDengine 查询引擎概览》
- 02-《TDengine SQL 解析与词法分析》
- 03-《TDengine 语义分析与 AST 重写》
- 04-《TDengine 逻辑计划生成》
- 05-《TDengine 物理计划生成》
- 06-《TDengine 扫描算子》
- 07-《TDengine 聚合算子》
- 08-《TDengine 连接算子》
- 09-《TDengine 排序、填充与投影》
- 10-《TDengine 分布式查询执行》
- 11-《TDengine EXPLAIN 与查询优化》
数据写入
- 01-《TDengine SQL INSERT》
- 02-《TDengine 无模式写入》
- 03-《TDengine STMT 写入》
- 04-《TDengine 写入内部流程》
- 05-《TDengine 数据更新删除》
数据订阅
- 01-《TDengine 数据订阅》
- 02-《TDengine 订阅 vs Kafka》
- 03-《TDengine TMQ 消费流程》
- 04-《TDengine 内部机制》
- 05-《TDengine TMQ 最佳实践》
预聚合
索引
SQL 语句
- 01-《TDengine DDL》
- 02-《TDengine DML SELECT》
- 03-《TDengine DML 函数完整参考》
- 04-《TDengine JOIN 完整语法》
- 05-《TDengine 窗口完整语法》
- 06-《TDengine 操作符与表达式》
- 07-《TDengine 系统表》
- 08-《TDengine SQL 与标准 SQL 差异》
客户端与连接器
- 01-《TDengine 的连接方式》
- 02-《TDengine C/C++ 连接器》
- 03-《TDengine java 连接器》
- 04-《TDengine Python 连接器》
- 05-《TDengine Go 与 Rust 连接器》
关于 TDengine
TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。
