ClickHouse C# client

await using var cmd2 = connection.CreateCommand("INSERT INTO temp_ids VALUES (1), (2), (3)");
await cmd2.ExecuteNonQueryAsync();

await using var cmd3 = connection.CreateCommand("SELECT * FROM users WHERE id IN (SELECT id FROM temp_ids)");
await using var reader = await cmd3.ExecuteReaderAsync();
```

## Supported data types[​](#supported-data-types "Direct link to Supported data types")

`ClickHouse.Driver` supports all ClickHouse data types. The tables below show the mappings between ClickHouse types and native .NET types when reading data from the database.

### Type mapping: reading from ClickHouse[​](#clickhouse-native-type-map-reading "Direct link to Type mapping: reading from ClickHouse")

#### Integer types[​](#type-map-reading-integer "Direct link to Integer types")

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ClickHouse Type .NET Type|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Int8 `sbyte`| UInt8 `byte`| Int16 `short`| UInt16 `ushort`| Int32 `int`| UInt32 `uint`| Int64 `long`| UInt64 `ulong`| Int128 `BigInteger`| UInt128 `BigInteger`| Int256 `BigInteger`| UInt256 `BigInteger` | | | | | | | | | | | | | | | | | | | | | | | | | |

---

#### Floating point types[​](#type-map-reading-floating-points "Direct link to Floating point types")

|  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- |
| ClickHouse Type .NET Type|  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | | Float32 `float`| Float64 `double`| BFloat16 `float` | | | | | | | |

---

#### Decimal types[​](#type-map-reading-decimal "Direct link to Decimal types")

|  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ClickHouse Type .NET Type|  |  |  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Decimal(P, S) `decimal` / `ClickHouseDecimal`| Decimal32(S) `decimal` / `ClickHouseDecimal`| Decimal64(S) `decimal` / `ClickHouseDecimal`| Decimal128(S) `decimal` / `ClickHouseDecimal`| Decimal256(S) `decimal` / `ClickHouseDecimal` | | | | | | | | | | | |

Note

Decimal type conversion is controlled via the UseCustomDecimals setting.

---

#### Boolean type[​](#type-map-reading-boolean "Direct link to Boolean type")

|  |  |  |  |
| --- | --- | --- | --- |
| ClickHouse Type .NET Type|  |  | | --- | --- | | Bool `bool` | | | |

---

#### String types[​](#type-map-reading-strings "Direct link to String types")

|  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- |
| ClickHouse Type .NET Type|  |  |  |  | | --- | --- | --- | --- | | String `string`| FixedString(N) `string` | | | | | |

Note

By default, both `String` and `FixedString(N)` columns are returned as `string`. Set `ReadStringsAsByteArrays=true` in your connection string to read them as `byte[]` instead. This is useful when storing binary data that may not be valid UTF-8.

---

#### Date and time types[​](#type-map-reading-datetime "Direct link to Date and time types")

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ClickHouse Type .NET Type|  |  |  |  |  |  |  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Date `DateTime`| Date32 `DateTime`| DateTime `DateTime`| DateTime32 `DateTime`| DateTime64 `DateTime`| Time `TimeSpan`| Time64 `TimeSpan` | | | | | | | | | | | | | | | |

ClickHouse stores `DateTime` and `DateTime64` values internally as Unix timestamps (seconds or sub-second units since epoch). While the storage is always in UTC, columns can have an associated timezone that affects how values are displayed and interpreted.

When reading `DateTime` values, the `DateTime.Kind` property is set based on the column's timezone:

|  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Column Definition Returned DateTime.Kind Notes|  |  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | `DateTime('UTC')` `Utc` Explicit UTC timezone|  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | | `DateTime('Europe/Amsterdam')` `Unspecified` Offset applied|  |  |  | | --- | --- | --- | | `DateTime` `Unspecified` Wall-clock time preserved as-is | | | | | | | | | | | |

For non-UTC columns, the returned `DateTime` represents the wall-clock time in that timezone. Use `ClickHouseDataReader.GetDateTimeOffset()` to get a `DateTimeOffset` with the correct offset for that timezone:

```
var reader = (ClickHouseDataReader)await connection.ExecuteReaderAsync(
    "SELECT toDateTime('2024-06-15 14:30:00', 'Europe/Amsterdam')");
reader.Read();

var dt = reader.GetDateTime(0);    // 2024-06-15 14:30:00, Kind=Unspecified
var dto = reader.GetDateTimeOffset(0); // 2024-06-15 14:30:00 +02:00 (CEST)
```

For columns **without** an explicit timezone (i.e., `DateTime` instead of `DateTime('Europe/Amsterdam')`), the driver returns a `DateTime` with `Kind=Unspecified`. This preserves the wall-clock time exactly as stored without making assumptions about timezone.

If you need timezone-aware behavior for columns without explicit timezones, either:

1. Use explicit timezones in your column definitions: `DateTime('UTC')` or `DateTime('Europe/Amsterdam')`
2. Apply the timezone yourself after reading.

---

#### JSON type[​](#type-map-reading-json "Direct link to JSON type")

|  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ClickHouse Type .NET Type Notes|  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | | Json `JsonObject` Default (`JsonReadMode=Binary`)| Json `string` When `JsonReadMode=String` | | | | | | | | |

The return type for JSON columns is controlled by the `JsonReadMode` setting:

- **`Binary` (default)**: Returns `System.Text.Json.Nodes.JsonObject`. Provides structured access to JSON data, but specialized ClickHouse types (like IP addresses, UUIDs, large decimals) are converted to their string representations within the JSON structure.
- **`String`**: Returns the raw JSON as a `string`. Preserves the exact JSON representation from ClickHouse, which is useful when you need to pass the JSON through without parsing, or when you want to handle deserialization yourself.

```
// Configure string mode via settings
var settings = new ClickHouseClientSettings("Host=localhost")
{
    JsonReadMode = JsonReadMode.String
};

// Or via connection string
// "Host=localhost;JsonReadMode=String"
```

---

#### Other types[​](#type-map-reading-other "Direct link to Other types")