CH.Native
1.1.1
See the version list below for details.
dotnet add package CH.Native --version 1.1.1
NuGet\Install-Package CH.Native -Version 1.1.1
<PackageReference Include="CH.Native" Version="1.1.1" />
<PackageVersion Include="CH.Native" Version="1.1.1" />
<PackageReference Include="CH.Native" />
paket add CH.Native --version 1.1.1
#r "nuget: CH.Native, 1.1.1"
#:package CH.Native@1.1.1
#addin nuget:?package=CH.Native&version=1.1.1
#tool nuget:?package=CH.Native&version=1.1.1
CH.Native
A high-performance modern .NET client for ClickHouse using the native binary TCP protocol.
Quick Start
dotnet add package CH.Native
await using var connection = new ClickHouseConnection("Host=localhost;Port=9000");
await connection.OpenAsync();
var result = await connection.ExecuteScalarAsync<int>("SELECT 1");
Console.WriteLine(result); // 1
See the Getting Started Guide for more examples, or run
samples/CH.Native.Samples.QuickStart for the same flow as a runnable project.
Features
- Native Binary Protocol - Direct TCP communication on port 9000 for optimal performance
- Full Async/Await - All operations are async with streaming support
- ADO.NET Provider - Standard
DbConnectionimplementation with Dapper compatibility - Bulk Insert - High-performance batched inserts with typed mapping
- Compression - LZ4 (default) and Zstd compression support
- Resilience - Built-in retry policies, circuit breakers, and health checking
- Load Balancing - Multi-server support with round-robin, random, or first-available strategies
- TLS/SSL - Secure connections with certificate validation
- Telemetry - OpenTelemetry-compatible tracing, metrics, and logging
- Type Safety - Full support for all ClickHouse types with .NET mapping
Supported ClickHouse Types
CH.Native supports the full ClickHouse type system across read, write, and bulk-insert paths. See Data Types for the complete CLR-mapping reference.
| Category | ClickHouse Types | .NET Mapping |
|---|---|---|
| Signed integers | Int8, Int16, Int32, Int64, Int128, Int256 |
sbyte, short, int, long, Int128, BigInteger |
| Unsigned integers | UInt8, UInt16, UInt32, UInt64, UInt128, UInt256 |
byte, ushort, uint, ulong, UInt128, BigInteger |
| Floating point | Float32, Float64, BFloat16 |
float, double, float |
| Fixed-point | Decimal32(S), Decimal64(S), Decimal128(S), Decimal256(S) |
decimal (or ClickHouseDecimal for D128/256 wide range) |
| Boolean | Bool |
bool |
| Date / Time | Date, Date32, DateTime, DateTime('Tz'), DateTime64(P), Time, Time64(P) |
DateOnly, DateTime, DateTimeOffset, TimeOnly |
| String | String, FixedString(N) |
string, byte[] |
| Network / IDs | UUID, IPv4, IPv6 |
Guid, IPAddress |
| Enums | Enum8, Enum16 |
sbyte, short (or your enum via cast) |
| Composites | Nullable(T), Array(T), Map(K,V), Tuple(...), Nested(...), LowCardinality(T) |
T?, T[], Dictionary<K,V>, object[], object[][], T (transparent) |
| Geospatial | Point, Ring, LineString, Polygon, MultiLineString, MultiPolygon |
Point, Point[], Point[][], Point[][][] |
| Semi-structured | JSON, Dynamic, Variant(T0, T1, ...) |
string / JsonDocument, ClickHouseDynamic, VariantValue<T0, T1> (boxing-free 2-arm) or ClickHouseVariant (boxed N-arm) |
All types round-trip through both the read path (ExecuteReaderAsync, QueryAsync<T>) and the bulk-insert path (CreateBulkInserter<T>). Nullable(...) wraps any non-composite type. Composites compose freely (e.g. Array(Nullable(LowCardinality(String)))).
Installation
dotnet add package CH.Native
Basic Usage
Execute a Query
await using var connection = new ClickHouseConnection("Host=localhost;Port=9000");
await connection.OpenAsync();
// Scalar query
var count = await connection.ExecuteScalarAsync<long>("SELECT count() FROM users");
// DDL/DML
await connection.ExecuteNonQueryAsync("CREATE TABLE IF NOT EXISTS users (id UInt32, name String) ENGINE = Memory");
Query with Parameters
var users = await connection.QueryAsync<User>(
"SELECT * FROM users WHERE age > @minAge",
new { minAge = 18 }
).ToListAsync();
Typed Results
public class User
{
public uint Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
await foreach (var user in connection.QueryAsync<User>("SELECT * FROM users"))
{
Console.WriteLine($"{user.Id}: {user.Name}");
}
Bulk Insert
var users = new List<User> { /* ... */ };
await using var inserter = connection.CreateBulkInserter<User>("users");
await inserter.InitAsync();
await inserter.AddRangeAsync(users);
await inserter.CompleteAsync();
ADO.NET / Dapper
await using var connection = new ClickHouseDbConnection("Host=localhost;Port=9000");
await connection.OpenAsync();
// Dapper
var users = await connection.QueryAsync<User>("SELECT * FROM users");
Documentation
| Guide | Description |
|---|---|
| Quick Start | Get up and running in minutes |
| Configuration | Connection strings, settings, TLS, multi-server |
| Authentication | Password, JWT, SSH key, mTLS, role activation |
| Connection Pooling | ClickHouseDataSource, sizing, observability |
| Dependency Injection | AddClickHouse, keyed services, providers, health checks |
| Data Types | ClickHouse to .NET type mapping reference |
| Resilience | Retry policies, circuit breakers, load balancing |
| Bulk Insert | High-performance data loading |
| ADO.NET & Dapper | Standard provider and ORM integration |
| LINQ Provider | connection.Table<T>(), operators, modifiers |
| Telemetry | Tracing, metrics, and logging |
Samples
End-to-end runnable console projects under samples/. Each picks a flavour by CLI arg, creates a temp table, runs the demo, and drops the table.
| Project | What it covers |
|---|---|
| QuickStart | Runnable mirror of docs/quickstart.md — open a connection, scalar query, bulk insert, typed read. Start here. |
| Queries | Every read path: scalar, reader, raw rows, typed, LINQ, ADO.NET, Dapper, pooled, resilient, progress, log analytics |
| Insert | Every write path: single, collection, async stream, one-shot bulk, long-lived, dynamic, pooled, cross-database, plain SQL |
| Hosting | ASP.NET host wiring: AddClickHouse, keyed DataSources, all four auth methods (password / JWT / SSH / mTLS) against a docker overlay, credential providers, per-request role activation, health checks, bulk insert |
Performance
Three-way comparison against ClickHouse.Driver (HTTP) and Octonica (native TCP).
Query Latency
| Benchmark | CH.Native | ClickHouse.Driver | Octonica |
|---|---|---|---|
| SELECT 1 | 586 μs | 978 μs | 878 μs |
| COUNT(*) 1M rows | 992 μs | 1,408 μs | 1,041 μs |
| SELECT 100 rows | 660 μs | 1,183 μs | 710 μs |
Large Result Sets
| Benchmark | CH.Native | CH.Native (Lazy) | ClickHouse.Driver | Octonica |
|---|---|---|---|---|
| Stream 1M rows | 100 ms | 58 ms | 263 ms | 77 ms |
| Materialize 1M rows | 234 ms | 319 ms | 442 ms | 202 ms |
Bulk Insert
| Benchmark | CH.Native | ClickHouse.Driver | Octonica |
|---|---|---|---|
| 1M rows | 97 ms | 205 ms | 1,489 ms |
Memory Efficiency (1M rows)
| Benchmark | CH.Native | CH.Native (Lazy) | ClickHouse.Driver | Octonica |
|---|---|---|---|---|
| Streaming | 121 MB | 25 MB | 191 MB | 78 MB |
| Bulk insert | 0.4 MB | — | 95 MB | 27 MB |
Enable lazy string materialization via connection string (StringMaterialization=Lazy) or builder (.WithStringMaterialization(StringMaterialization.Lazy)). Lazy mode defers UTF-8 string decoding until values are accessed, reducing memory by ~68% for streaming reads. Best for ExecuteReaderAsync / QueryAsync workloads; typed queries (QueryAsync<T>) always use eager decoding.
Apple M5, .NET 10.0, ClickHouse 25.3 — run benchmarks with dotnet run --project benchmarks/CH.Native.Benchmarks -c Release
Requirements
- .NET 8.0, 9.0, or 10.0
- ClickHouse server with native protocol enabled (port 9000)
Contributing
Contributions are welcome! Please feel free to submit issues and pull requests.
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Submit a pull request
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
| Product | Versions 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 is compatible. 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 is compatible. 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. |
-
net10.0
- K4os.Compression.LZ4 (>= 1.3.8)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.3)
- SSH.NET (>= 2024.2.0)
- ZstdSharp.Port (>= 0.8.8)
-
net8.0
- K4os.Compression.LZ4 (>= 1.3.8)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.3)
- SSH.NET (>= 2024.2.0)
- System.IO.Pipelines (>= 8.0.0)
- ZstdSharp.Port (>= 0.8.8)
-
net9.0
- K4os.Compression.LZ4 (>= 1.3.8)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.3)
- SSH.NET (>= 2024.2.0)
- ZstdSharp.Port (>= 0.8.8)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on CH.Native:
| Package | Downloads |
|---|---|
|
CH.Native.DependencyInjection
Microsoft.Extensions.DependencyInjection integration for CH.Native. Registers ClickHouseDataSource as a singleton, supports keyed multi-database setups, IConfiguration binding, rotating-credential providers (JWT, SSH key, mTLS cert), and ASP.NET health checks. |
|
|
CH.Native.Dapper
Dapper integration for CH.Native. Registers type handlers for array-typed parameters (int[], string[], long[], Guid[], etc.) so `new { ids = arr }` binds as a ClickHouse Array(T) on the wire instead of being expanded into a Tuple by Dapper's default list-expansion behaviour. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.2-prerelease.33 | 55 | 5/30/2026 |
| 1.1.2-prerelease.32 | 57 | 5/30/2026 |
| 1.1.2-prerelease.31 | 65 | 5/20/2026 |
| 1.1.2-prerelease.30 | 60 | 5/18/2026 |
| 1.1.2-prerelease.29 | 65 | 5/17/2026 |
| 1.1.2-prerelease.28 | 60 | 5/17/2026 |
| 1.1.2-prerelease.27 | 56 | 5/17/2026 |
| 1.1.2-prerelease.26 | 56 | 5/15/2026 |
| 1.1.1 | 141 | 5/9/2026 |
| 1.1.1-prerelease.25 | 69 | 5/9/2026 |
| 1.1.1-prerelease.24 | 81 | 5/8/2026 |
| 1.1.1-prerelease.23 | 63 | 5/7/2026 |
| 1.1.0 | 134 | 5/6/2026 |
| 1.1.0-prerelease.22 | 62 | 5/6/2026 |
| 1.0.1-prerelease.21 | 62 | 5/6/2026 |
| 1.0.1-prerelease.20 | 57 | 5/6/2026 |
| 1.0.1-prerelease.19 | 57 | 5/5/2026 |
| 1.0.1-prerelease.18 | 66 | 5/4/2026 |
| 1.0.1-prerelease.17 | 59 | 5/2/2026 |
| 1.0.1-prerelease.15 | 64 | 4/26/2026 |