CH.Native.DependencyInjection
1.1.1
See the version list below for details.
dotnet add package CH.Native.DependencyInjection --version 1.1.1
NuGet\Install-Package CH.Native.DependencyInjection -Version 1.1.1
<PackageReference Include="CH.Native.DependencyInjection" Version="1.1.1" />
<PackageVersion Include="CH.Native.DependencyInjection" Version="1.1.1" />
<PackageReference Include="CH.Native.DependencyInjection" />
paket add CH.Native.DependencyInjection --version 1.1.1
#r "nuget: CH.Native.DependencyInjection, 1.1.1"
#:package CH.Native.DependencyInjection@1.1.1
#addin nuget:?package=CH.Native.DependencyInjection&version=1.1.1
#tool nuget:?package=CH.Native.DependencyInjection&version=1.1.1
CH.Native.DependencyInjection
Microsoft.Extensions.DependencyInjection integration for CH.Native, the high-performance .NET client for ClickHouse using the native binary TCP protocol.
Registers ClickHouseDataSource as a singleton with optional keyed multi-database setups, IConfiguration binding, rotating-credential providers, and ASP.NET health checks.
Install
dotnet add package CH.Native.DependencyInjection
Usage
Connection string
builder.Services.AddClickHouse("Host=localhost;Database=default;Username=default");
Fluent builder
builder.Services.AddClickHouse(b => b
.WithHost("clickhouse.internal")
.WithDatabase("analytics")
.WithCompression(true)
.WithCompressionMethod(CompressionMethod.LZ4));
From IConfiguration
// appsettings.json
{
"ClickHouse": {
"Host": "clickhouse.internal",
"Database": "analytics",
"Username": "reader",
"Pool": {
"MaxPoolSize": 64,
"PrewarmOnStart": true
}
}
}
builder.Services.AddClickHouse(builder.Configuration.GetSection("ClickHouse"));
Resolve and use
ClickHouseDataSource is a singleton; open a connection per unit of work. The connection returns to the pool on DisposeAsync.
public class EventsController(ClickHouseDataSource dataSource) : ControllerBase
{
[HttpGet]
public async IAsyncEnumerable<Event> GetEvents()
{
await using var conn = await dataSource.OpenConnectionAsync();
await foreach (var row in conn.QueryAsync<Event>("SELECT * FROM events LIMIT 1000"))
yield return row;
}
}
Multiple databases (keyed)
builder.Services.AddClickHouse("analytics", analyticsConnString);
builder.Services.AddClickHouse("logs", logsConnString);
public class Reporter([FromKeyedServices("analytics")] ClickHouseDataSource ds) { }
Rotating credentials
Plug in providers for short-lived credentials (JWT, SSH key, mTLS cert, password). Each new physical connection re-resolves the credential.
builder.Services
.AddClickHouse("Host=clickhouse.internal;Database=analytics")
.WithJwtProvider<MyJwtProvider>();
public sealed class MyJwtProvider(IAccessTokenService tokens) : IClickHouseJwtProvider
{
public ValueTask<string> GetTokenAsync(CancellationToken ct) => tokens.GetClickHouseTokenAsync(ct);
}
Equivalent interfaces exist for password (IClickHousePasswordProvider), SSH key (IClickHouseSshKeyProvider), and mTLS client certificate (IClickHouseCertificateProvider).
Invocation cadence
The contract is deliberately tied to physical connections, not queries or failures:
- Once per physical connection. The provider is invoked when the pool builds a fresh socket — cold start, post-discard rent, or post-eviction rent. Subsequent queries on the same rented connection re-use the credential resolved at open-time; the provider is not re-queried per query.
- Staleness bound:
ConnectionLifetime(default 30 min). This is the upper bound on how long the pool will keep using a credential resolved by a previous provider call. SetConnectionLifetimeto match or undercut your token TTL so the pool recycles connections — and refreshes credentials — before they expire. - Failure-driven refresh is not guaranteed. A query failure may or may not cause the provider to be re-invoked on the next rent, depending on whether the pool discards the connection. Failures that trip the discard path (protocol-fatal errors,
KILL QUERYon an in-flight query, force-disposed connections) cause the next rent to build a fresh socket and re-query the provider. Failures that leave the connection structurally healthy (server-side SQL errors, transient cancellations) keep the connection in the pool and the credential is reused. Do not design rotation around "any failure forces a refresh". - Rotate by lifetime, not by retry. If you need faster credential rotation, lower
ConnectionLifetime. Worst case: a connection rented just before a token rotation may keep using the old token for up toConnectionLifetimebefore the pool recycles it.
Provider implementations should handle their own caching/refresh internally (e.g. Azure.Identity's TokenCredential caches under the hood) — the pool will call you on every physical-connection build, not just when the credential has actually changed.
Validation cadence
Options validation is split so that chained provider registration is allowed:
Shape errors fail fast at registration time. Bad pool sizes (
MaxPoolSize < 1,MinPoolSize > MaxPoolSize), out-of-range ports, negative timeouts — all throw insideAddClickHouse(IConfiguration)before it returns.Auth-pairing errors surface at first DataSource resolution.
AuthMethod=Jwtwithout aJwtTokenor a chainedWithJwtProvider<>(), andAuthMethod=SshKeywithout aSshPrivateKeyPathorWithSshKeyProvider<>(), throw the first time something resolvesClickHouseDataSource. This lets the chained provider call satisfy the requirement instead of being a false-positive registration-time error.ValidateOnStart()opt-in for fail-fast at host startup. Apps that want the auth-pairing check to fail duringHost.StartAsync()rather than at the first request can chain.ValidateOnStart():builder.Services .AddClickHouse(builder.Configuration.GetSection("ClickHouse")) .WithJwtProvider<MyJwtProvider>() .ValidateOnStart();Internally this registers a small
IHostedServicethat resolves the DataSource inStartAsync, triggering the deferred validator.
Health checks
builder.Services.AddHealthChecks()
.AddClickHouse(name: "clickhouse");
License
MIT
| 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
- CH.Native (>= 1.1.1)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 8.0.26)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
-
net8.0
- CH.Native (>= 1.1.1)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 8.0.26)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
-
net9.0
- CH.Native (>= 1.1.1)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 8.0.26)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
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 |
|---|---|---|
| 1.1.2-prerelease.33 | 44 | 5/30/2026 |
| 1.1.2-prerelease.32 | 56 | 5/30/2026 |
| 1.1.2-prerelease.31 | 56 | 5/20/2026 |
| 1.1.2-prerelease.30 | 51 | 5/18/2026 |
| 1.1.2-prerelease.29 | 53 | 5/17/2026 |
| 1.1.2-prerelease.28 | 56 | 5/17/2026 |
| 1.1.2-prerelease.27 | 49 | 5/17/2026 |
| 1.1.2-prerelease.26 | 55 | 5/15/2026 |
| 1.1.1 | 103 | 5/9/2026 |
| 1.1.1-prerelease.25 | 55 | 5/9/2026 |
| 1.1.1-prerelease.24 | 73 | 5/8/2026 |
| 1.1.1-prerelease.23 | 54 | 5/7/2026 |
| 1.1.0 | 94 | 5/6/2026 |
| 1.1.0-prerelease.22 | 43 | 5/6/2026 |
| 1.0.1-prerelease.21 | 49 | 5/6/2026 |
| 1.0.1-prerelease.20 | 44 | 5/6/2026 |
| 1.0.1-prerelease.19 | 46 | 5/5/2026 |
| 1.0.1-prerelease.18 | 57 | 5/4/2026 |
| 1.0.1-prerelease.17 | 55 | 5/2/2026 |
| 1.0.1-prerelease.15 | 61 | 4/26/2026 |