ClickHouse C# client
The official C# client for connecting to ClickHouse. The client source code is available in the GitHub repository. Originally developed by Oleg V. Kozlyuk.
Migration guide
- Update your
.csprojfile with the new package nameClickHouse.Driverand the latest version on NuGet. - Update all
ClickHouse.Clientreferences toClickHouse.Driverin your codebase.
Supported .NET versions
ClickHouse.Driver supports the following .NET versions:
- .NET Framework 4.6.2
- .NET Framework 4.8
- .NET Standard 2.1
- .NET 6.0
- .NET 8.0
- .NET 9.0
Installation
Install the package from NuGet:
Or using the NuGet Package Manager:
Quick start
Using Dapper:
Usage
Connection string parameters
| Parameter | Description | Default |
|---|---|---|
Host | ClickHouse server address | localhost |
Port | ClickHouse server port | 8123 or 8443 (depending on Protocol) |
Database | Initial database | default |
Username | Authentication username | default |
Password | Authentication password | (empty) |
Protocol | Connection protocol (http or https) | http |
Compression | Enables Gzip compression | true |
UseSession | Enables persistent server session | false |
SessionId | Custom session ID | Random GUID |
Timeout | HTTP timeout (seconds) | 120 |
UseServerTimezone | Use server timezone for datetime columns | true |
UseCustomDecimals | Use ClickHouseDecimal for decimals | false |
Example: Host=clickhouse;Port=8123;Username=default;Password=;Database=default
UseSession flag enables persistence of server session, allowing use of SET statements and temp tables. Session will be reset after 60 seconds of inactivity (default timeout). Session lifetime can be extended by setting session settings via ClickHouse statements.
ClickHouseConnection class normally allows for parallel operation (multiple threads can run queries concurrently). However, enabling UseSession flag will limit that to one active query per connection at any moment of time (server-side limitation).
Connection lifetime and pooling
ClickHouse.Driver uses System.Net.Http.HttpClient under the hood. HttpClient has a per-endpoint connection pool. As a consequence:
- A
ClickHouseConnectionobject does not have 1:1 mapping to TCP connections - multiple database sessions will be multiplexed through several (2 by default) TCP connections per server. - Connections can stay alive after
ClickHouseConnectionobject was disposed. - This behavior can be tweaked by passing a bespoke
HttpClientwith customHttpClientHandler.
For DI environments, there is a bespoke constructor ClickHouseConnection(string connectionString, IHttpClientFactory httpClientFactory, string httpClientName = "") which allows to generalize HTTP client settings.
Recommendations:
- A
ClickHouseConnectionrepresents a "session" with the server. It performs feature discovery by querying server version (so there is a minor overhead on opening), but generally it is safe to create and destroy such objects multiple times. - Recommended lifetime for a connection is one connection object per large "transaction" spanning multiple queries. There is a minor overhead on connection startup, so it's not recommended to create a connection object for each query.
- If an application operates on large volumes of transactions and requires to create/destroy
ClickHouseConnectionobjects often, it is recommended to useIHttpClientFactoryor a static instance ofHttpClientto manage connections.
Creating a table
Create a table using standard SQL syntax:
Inserting data
Insert data using parameterized queries:
Bulk insert
Using ClickHouseBulkCopy requires:
- Target connection (
ClickHouseConnectioninstance) - Target table name (
DestinationTableNameproperty) - Data source (
IDataReaderorIEnumerable<object[]>)
- For optimal performance, ClickHouseBulkCopy uses the Task Parallel Library (TPL) to process batches of data, with up to 4 parallel insertion tasks (this can be tuned).
- Column names can be optionally provided via
ColumnNamesproperty if source data has fewer columns than target table. - Configurable parameters:
Columns,BatchSize,MaxDegreeOfParallelism. - Before copying, a
SELECT * FROM <table> LIMIT 0query is performed to get information about target table structure. Types of provided objects must reasonably match the target table. - Sessions are not compatible with parallel insertion. Connection passed to
ClickHouseBulkCopymust have sessions disabled, orMaxDegreeOfParallelismmust be set to1.
Performing SELECT queries
Execute SELECT queries and process results:
Raw streaming
Nested columns support
ClickHouse nested types (Nested(...)) can be read and written using array semantics.
AggregateFunction columns
Columns of type AggregateFunction(...) cannot be queried or inserted directly.
To insert:
To select:
SQL parameters
To pass parameters in query, ClickHouse parameter formatting must be used, in following form:
Examples:
- SQL 'bind' parameters are passed as HTTP URI query parameters, so using too many of them may result in a "URL too long" exception.
- To insert large volume of records, consider using Bulk Insert functionality.
Supported data types
ClickHouse.Driver supports the following ClickHouse data types with their corresponding .NET type mappings:
Boolean types
Bool→bool
Numeric types
Signed Integers:
Int8→sbyteInt16→shortInt32→intInt64→longInt128→BigIntegerInt256→BigInteger
Unsigned Integers:
UInt8→byteUInt16→ushortUInt32→uintUInt64→ulongUInt128→BigIntegerUInt256→BigInteger
Floating Point:
Float32→floatFloat64→double
Decimal:
Decimal→decimalDecimal32→decimalDecimal64→decimalDecimal128→decimalDecimal256→BigDecimal
String types
String→stringFixedString→string
Date and time types
Date→DateTimeDate32→DateTimeDateTime→DateTimeDateTime32→DateTimeDateTime64→DateTime
Network types
IPv4→IPAddressIPv6→IPAddress
Geographic types
Point→TupleRing→Array of PointsPolygon→Array of Rings
Complex types
Array(T)→Array of any typeTuple(T1, T2, ...)→Tuple of any typesNullable(T)→Nullable version of any typeMap(K, V)→Dictionary<K, V>
DateTime handling
ClickHouse.Driver tries to correctly handle timezones and DateTime.Kind property. Specifically:
DateTimevalues are returned as UTC. User can then convert them themselves or useToLocalTime()method onDateTimeinstance.- When inserting,
DateTimevalues are handled in following way:UTCDateTimes are inserted 'as is', because ClickHouse stores them in UTC internally.LocalDateTimes are converted to UTC according to user's local timezone settings.UnspecifiedDateTimes are considered to be in target column's timezone, and hence are converted to UTC according to that timezone.
- For columns without timezone specified, client timezone is used by default (legacy behavior).
UseServerTimezoneflag in connection string can be used to use server timezone instead.
Environment variables
You can set defaults using environment variables:
| Variable | Purpose |
|---|---|
CLICKHOUSE_DB | Default database |
CLICKHOUSE_USER | Default username |
CLICKHOUSE_PASSWORD | Default password |
Values provided explicitly to the ClickHouseConnection constructor will take priority over environment variables.
ORM & Dapper support
ClickHouse.Driver supports Dapper (with limitations).
Working example:
Not supported: