Thunderduck.Data 0.1.0

dotnet add package Thunderduck.Data --version 0.1.0
                    
NuGet\Install-Package Thunderduck.Data -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Thunderduck.Data" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Thunderduck.Data" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Thunderduck.Data" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Thunderduck.Data --version 0.1.0
                    
#r "nuget: Thunderduck.Data, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Thunderduck.Data@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Thunderduck.Data&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Thunderduck.Data&version=0.1.0
                    
Install as a Cake Tool

Thunderduck.Data

ADO.NET provider and async client for thunderduck. It lets .NET 8+ applications query thunderduck catalogs with plain ADO.NET, Dapper or DataTable. It has no third-party dependencies.

dotnet add package Thunderduck.Data

You need an API token (tdk_…). Create one in the console under Settings → API tokens. Load it from configuration or a secret store, and never hard-code it.

Connection string

Key Default Meaning
Host — API host, e.g. api.thunderduck.io
Token — API token (tdk_…). Removed from ConnectionString after Open()
Ssl true HTTPS
Port — Optional port
PollInterval 1000 How often a running query is polled, in ms
Timeout 300 Default query timeout in seconds (CommandTimeout overrides it)
PageSize 1000 Rows fetched per page while reading

ADO.NET

using Thunderduck.Data;

await using var conn = new ThunderduckConnection(
    $"Host=api.thunderduck.io;Token={token}");
await conn.OpenAsync();            // validates the token

await using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT order_id, total_amount FROM pg.public.orders WHERE total_amount > @min";
cmd.Parameters.AddWithValue("min", 100m);

await using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
    Console.WriteLine($"{reader.GetInt64(0)}: {reader.GetDecimal(1)}");

Address tables as catalog.schema.table, or catalog.table for two-level catalogs. There is no current database.

Dapper

using Dapper;

var orders = await conn.QueryAsync<Order>(
    "SELECT order_id AS Id, total_amount AS Total FROM pg.public.orders WHERE total_amount > @min",
    new { min = 100m });

public sealed record Order(long Id, decimal Total);

Typed client

Use the client when you want to submit, wait and page yourself:

using Thunderduck.Client;

var client = new ThunderduckClient(new ThunderduckClientOptions {
    BaseUri = new Uri("https://api.thunderduck.io"), Token = token });

string id = await client.SubmitAsync("SELECT * FROM lake.events", ct);
await client.WaitAsync(id, TimeSpan.FromMinutes(10), ct);
await foreach (var page in client.ReadPagesAsync(id, pageSize: 5000, ct))
    Console.WriteLine($"{page.Offset}..{page.Offset + page.Rows.Count} of {page.Total}");

Pass your own HttpClient, for example one from IHttpClientFactory, in ThunderduckClientOptions.HttpClient.

Cancellation

Each of these stops waiting and cancels the query on the server:

  • cancelling the CancellationToken;
  • calling DbCommand.Cancel(), which works from another thread;
  • the timeout running out.

A cancelled caller doesn't leave a job running.

Browsing the catalog

GetSchema() reads the catalog API and doesn't run SQL. Collections:

Collection Columns Restrictions
MetaDataCollections CollectionName, NumberOfRestrictions —
Catalogs CATALOG_NAME, CATALOG_TYPE, ERROR catalog
Schemas CATALOG_NAME, SCHEMA_NAME catalog, schema
Tables CATALOG_NAME, SCHEMA_NAME, TABLE_NAME, TABLE_TYPE catalog, schema, table
Columns CATALOG_NAME, SCHEMA_NAME, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE catalog, schema, table, column
var columns = conn.GetSchema("Columns", new[] { "pg", "public", "orders" });

Types

DuckDB .NET (GetFieldType)
BOOLEAN bool
TINYINT / SMALLINT / INTEGER / BIGINT sbyte / short / int / long
UTINYINT / USMALLINT / UINTEGER / UBIGINT byte / ushort / uint / ulong
HUGEINT / UHUGEINT System.Numerics.BigInteger
FLOAT / DOUBLE float / double
DECIMAL(p,s) decimal (exact)
DATE DateTime (midnight); GetFieldValue<DateOnly> too
TIME TimeSpan; GetFieldValue<TimeOnly> too
TIMESTAMP DateTime (Kind Unspecified)
TIMESTAMP WITH TIME ZONE DateTime (Kind Utc); GetFieldValue<DateTimeOffset> keeps the offset
UUID Guid
BLOB byte[]
VARCHAR / JSON / ENUM / INTERVAL string
LIST / STRUCT / MAP string (raw JSON), or GetFieldValue<JsonElement>

As in Npgsql, DATE, TIME and TIMESTAMPTZ come back as DateTime/TimeSpan, so Dapper and DataTable map them onto ordinary properties.

Parameters accept these .NET types plus DateOnly, TimeOnly, DateTimeOffset and char. The driver inlines them into the SQL as typed DuckDB literals, because the API has no server-side parameter binding.

Limits

  • Each query runs as a job, so expect seconds before the first row. Don't use it for tight OLTP loops.
  • There are no transactions or batches, and RecordsAffected is always -1.
  • Parameters are inlined into the SQL by the client as literals; the server doesn't bind them.
  • Results are read from the stored result. Stored results expire after one day, and reading an expired one throws ThunderduckException with Kind = ResultExpired.

Errors

Every failure is a ThunderduckException (a DbException) with:

  • Kind: Authentication, QueryFailed, Cancelled, Timeout, ResultExpired or Http;
  • HttpStatus;
  • ExecutionId.

The message is the server's error. It never contains the token.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 81 10/9/2026