Skip to main content

TDengine C# Client Library

TDengine.Connector is the official C# client library for TDengine. C# developers can develop applications to access TDengine instance data.

This article describes how to install TDengine.Connector in a Linux or Windows environment and connect to TDengine clusters via TDengine.Connector to perform basic operations such as data writing and querying.

The source code for TDengine.Connector is hosted on GitHub.

Version support

Please refer to version support list

Installation

Pre-installation

Add TDengine.Connector through Nuget

dotnet add package TDengine.Connector

Establishing a connection

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="3.0.*" GeneratePathProperty="true" />
</ItemGroup>
<Target Name="copyDLLDependency" BeforeTargets="BeforeBuild">
<ItemGroup>
<DepDLLFiles Include="$(PkgTDengine_Connector)\runtimes\**\*.*" />
</ItemGroup>
<Copy SourceFiles="@(DepDLLFiles)" DestinationFolder="$(OutDir)" />
</Target>

</Project>

view source code

using System;
using TDengineWS.Impl;

namespace Cloud.Examples
{
public class ConnectExample
{
static void Main(string[] args)
{
string dsn = Environment.GetEnvironmentVariable("TDENGINE_CLOUD_DSN");
Connect(dsn);
}

public static void Connect(string dsn)
{
// get connect
IntPtr conn = LibTaosWS.WSConnectWithDSN(dsn);
if (conn == IntPtr.Zero)
{
throw new Exception($"get connection failed,reason:{LibTaosWS.WSErrorStr(conn)},code:{LibTaosWS.WSErrorNo(conn)}");
}
else
{
Console.WriteLine("Establish connect success.");
}

// do something ...

// close connect
LibTaosWS.WSClose(conn);

}
}
}

view source code

Usage examples

Basic Insert and Query

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="3.0.*" GeneratePathProperty="true" />
</ItemGroup>
<Target Name="copyDLLDependency" BeforeTargets="BeforeBuild">
<ItemGroup>
<DepDLLFiles Include="$(PkgTDengine_Connector)\runtimes\**\*.*" />
</ItemGroup>
<Copy SourceFiles="@(DepDLLFiles)" DestinationFolder="$(OutDir)" />
</Target>

</Project>

view source code

using System;
using TDengineDriver;
using TDengineWS.Impl;
using System.Collections.Generic;

namespace Cloud.Examples
{
public class UsageExample
{
static void Main(string[] args)
{
string dsn = Environment.GetEnvironmentVariable("TDENGINE_CLOUD_DSN");
IntPtr conn = Connect(dsn);
InsertData(conn);
SelectData(conn);
// close connect
LibTaosWS.WSClose(conn);
}

public static IntPtr Connect(string dsn)
{
// get connect
IntPtr conn = LibTaosWS.WSConnectWithDSN(dsn);
if (conn == IntPtr.Zero)
{
throw new Exception($"get connection failed,reason:{LibTaosWS.WSErrorStr(conn)},code:{LibTaosWS.WSErrorNo(conn)}");
}
return conn;
}


public static void InsertData(IntPtr conn)
{
string createTable = "CREATE STABLE if not exists test.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)";
string insertData = "INSERT INTO " +
"test.d1001 USING test.meters TAGS('California.SanFrancisco', 1) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000)" +
"test.d1002 USING test.meters TAGS('California.SanFrancisco', 2) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000)" +
"test.d1003 USING test.meters TAGS('California.LosAngeles', 3) VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000)" +
"test.d1004 USING test.meters TAGS('California.LosAngeles', 4) VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ";

// create database under database named 'test'
IntPtr res = LibTaosWS.WSQuery(conn, createTable);
ValidQueryExecution(res);
// Free the query result every time when used up it.
LibTaosWS.WSFreeResult(res);

// insert data into the table created in previous step.
res = LibTaosWS.WSQuery(conn, insertData);
ValidQueryExecution(res);
// Free the query result every time when used up it.
LibTaosWS.WSFreeResult(res);
}
public static void SelectData(IntPtr conn)
{
string selectTable = "select * from test.meters";
IntPtr res = LibTaosWS.WSQueryTimeout(conn, selectTable,5000);
ValidQueryExecution(res);

// print meta
List<TDengineMeta> metas = LibTaosWS.WSGetFields(res);
foreach (var meta in metas)
{
Console.Write("{0} {1}({2})\t|", meta.name, meta.TypeName(), meta.size);
}
Console.WriteLine("");
List<object> dataSet = LibTaosWS.WSGetData(res);
for (int i = 0; i < dataSet.Count;)
{
for (int j = 0; j < metas.Count; j++)
{
Console.Write("{0}\t|\t", dataSet[i]);
i++;
}
Console.WriteLine("");
}
Console.WriteLine("");

// Free the query result every time when used up it.
LibTaosWS.WSFreeResult(res);
}

// Check if LibTaosWS.Query() execute correctly.
public static void ValidQueryExecution(IntPtr res)
{
int code = LibTaosWS.WSErrorNo(res);
if (code != 0)
{
throw new Exception($"execute SQL failed: reason: {LibTaosWS.WSErrorStr(res)}, code:{code}");
}
}
}
}

view source code

STMT Insert

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="3.0.*" GeneratePathProperty="true" />
</ItemGroup>
<Target Name="copyDLLDependency" BeforeTargets="BeforeBuild">
<ItemGroup>
<DepDLLFiles Include="$(PkgTDengine_Connector)\runtimes\**\*.*" />
</ItemGroup>
<Copy SourceFiles="@(DepDLLFiles)" DestinationFolder="$(OutDir)" />
</Target>
</Project>

view source code

using System;
using TDengineWS.Impl;
using TDengineDriver;
using System.Runtime.InteropServices;

namespace Cloud.Examples
{
public class STMTExample
{
static void Main(string[] args)
{
string dsn = Environment.GetEnvironmentVariable("TDENGINE_CLOUD_DSN");
IntPtr conn = Connect(dsn);
// assume table has been created.
// CREATE STABLE if not exists test.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)
string insert = "insert into ? using test.meters tags(?,?) values(?,?,?,?)";

// Init STMT
IntPtr stmt = LibTaosWS.WSStmtInit(conn);

if (stmt != IntPtr.Zero)
{
// Prepare SQL
int code = LibTaosWS.WSStmtPrepare(stmt, insert);
ValidSTMTStep(code, stmt, "WSInit()");

// Bind child table name and tags
TAOS_MULTI_BIND[] tags = new TAOS_MULTI_BIND[2] { WSMultiBind.WSBindBinary(new string[] { "California.LosAngeles" }), WSMultiBind.WSBindInt(new int?[] { 6 }) };
code = LibTaosWS.WSStmtSetTbnameTags(stmt, "test.d1005",tags, 2);
ValidSTMTStep(code, stmt, "WSStmtSetTbnameTags()");

// bind column value
TAOS_MULTI_BIND[] data = new TAOS_MULTI_BIND[4];
data[0] = WSMultiBind.WSBindTimestamp(new long[] { 1538551000000, 1538552000000, 1538553000000, 1538554000000, 1538555000000 });
data[1] = WSMultiBind.WSBindFloat(new float?[] { 10.30000F, 10.30000F, 11.30000F, 10.30000F, 10.80000F });
data[2] = WSMultiBind.WSBindInt(new int?[] { 218, 219, 221, 222, 223 });
data[3] = WSMultiBind.WSBindFloat(new float?[] { 0.28000F, 0.29000F, 0.30000F, 0.31000F, 0.32000F });
code = LibTaosWS.WSStmtBindParamBatch(stmt, data, 4);
ValidSTMTStep(code, stmt, "WSStmtBindParamBatch");

LibTaosWS.WSStmtAddBatch(stmt);
ValidSTMTStep(code, stmt, "WSStmtAddBatch");

IntPtr affectRowPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Int32)));
LibTaosWS.WSStmtExecute(stmt, affectRowPtr);
ValidSTMTStep(code, stmt, "WSStmtExecute");
Console.WriteLine("STMT affect rows:{0}", Marshal.ReadInt32(affectRowPtr));

LibTaosWS.WSStmtClose(stmt);

// Free allocated memory
Marshal.FreeHGlobal(affectRowPtr);
WSMultiBind.WSFreeTaosBind(tags);
WSMultiBind.WSFreeTaosBind(data);
}
// close connect
LibTaosWS.WSClose(conn);
}

public static IntPtr Connect(string dsn)
{
// get connect
IntPtr conn = LibTaosWS.WSConnectWithDSN(dsn);
if (conn == IntPtr.Zero)
{
throw new Exception($"get connection failed,reason:{LibTaosWS.WSErrorStr(conn)},code:{LibTaosWS.WSErrorNo(conn)}");
}
return conn;
}

public static void ValidSTMTStep(int code, IntPtr wsStmt, string method)
{
if (code != 0)
{
throw new Exception($"{method} failed,reason: {LibTaosWS.WSErrorStr(wsStmt)}, code: {code}");
}
else
{
Console.WriteLine("{0} success", method);
}
}
}
}

view source code

Important Updates

TDengine.ConnectorDescription
3.0.2Support .NET Framework 4.5 and above. Support .Net standard 2.0. Nuget package includes dynamic library for WebSocket.
3.0.1Support WebSocket and Cloud,With function query, insert, and parameter binding
3.0.0Supports TDengine 3.0.0.0. TDengine 2.x is not supported. Added TDengine.Impl.GetData() interface to deserialize query results.
1.0.7Fixed TDengine.Query() memory leak.
1.0.6Fix schemaless bug in 1.0.4 and 1.0.5.
1.0.5Fix Windows sync query Chinese error bug.
1.0.4Add asynchronous query, subscription, and other functions. Fix the binding parameter bug.
1.0.3Add parameter binding, schemaless, JSON tag, etc.
1.0.2Add connection management, synchronous query, error messages, etc.

Other descriptions

Third-party driver

Taos is an ADO.NET client library for TDengine, supporting Linux and Windows platforms. Community contributor Maikebing@@maikebing contributes the library. Please refer to:

Frequently Asked Questions

  1. "Unable to establish connection", "Unable to resolve FQDN"

Usually, it's caused by an incorrect FQDN configuration. Please refer to this section in the FAQ to troubleshoot.

  1. Unhandled exception. System.DllNotFoundException: Unable to load DLL 'taos' or one of its dependencies: The specified module cannot be found.

This is usually because the program did not find the dependent client driver. The solution is to copy C:\TDengine\driver\taos.dll to the C:\Windows\System32\ directory on Windows, and create the following soft link on Linux ln -s /usr/local/taos/driver/libtaos.so.x.x .x.x /usr/lib/libtaos.so will work.

API Reference

API Reference