Releases: ClickHouse/clickhouse-cs
1.2.0
What's Changed
- Bump Dapper from 2.1.35 to 2.1.72 by @dependabot[bot] in #259
- Bump linq2db from 6.1.0 to 6.2.0 by @dependabot[bot] in #260
- Bump Microsoft.Extensions.Configuration and Microsoft.Extensions.Configuration.Json by @dependabot[bot] in #262
- +26.3 -25.3 -25.12 from test matrix by @alex-clickhouse in #265
- Bump Microsoft.Extensions.Diagnostics.HealthChecks from 10.0.3 to 10.0.5 by @dependabot[bot] in #263
- Bump codecov/codecov-action from 5 to 6 by @dependabot[bot] in #267
- Bump linq2db from 6.2.0 to 6.2.1 by @dependabot[bot] in #270
- Bump Microsoft.Extensions.Logging.Abstractions from 10.0.3 to 10.0.5 by @dependabot[bot] in #271
- Update copilot-instructions.md by @alex-clickhouse in #272
- Infer IPv4 vs IPv6 from IPAddress value in TypeConverter by @alex-clickhouse in #266
- Bump Microsoft.Extensions.Logging.Console from 10.0.3 to 10.0.5 by @dependabot[bot] in #278
- Bump GitHubActionsTestLogger from 3.0.1 to 3.0.2 by @dependabot[bot] in #276
- Bump Microsoft.Extensions.Http from 10.0.3 to 10.0.5 by @dependabot[bot] in #277
- Bugfix: set json read/write setting for binary mode too by @alex-clickhouse in #282
- Parameter type resolution extensibility by @alex-clickhouse in #275
- Add support for POCO inserts by @alex-clickhouse in #273
- fix changelog and releasenotes by @alex-clickhouse in #283
- Bump Testcontainers.ClickHouse from 4.10.0 to 4.11.0 by @dependabot[bot] in #290
- Bump GitHubActionsTestLogger from 3.0.2 to 3.0.3 by @dependabot[bot] in #286
Full Changelog: 1.1.0...1.2.0
1.1.0
What's Changed
- Update README.md by @alex-clickhouse in #246
- Create context7.json by @alex-clickhouse in #247
- Throw on parallel inserts while using sessions by @alex-clickhouse in #251
- Bump Dapper from 2.1.66 to 2.1.72 by @dependabot[bot] in #252
- Bump Polly from 8.5.2 to 8.6.6 by @dependabot[bot] in #255
- Bump NUnit.Analyzers from 4.11.2 to 4.12.0 by @dependabot[bot] in #254
- fix bug with variant NULL parsing by @alex-clickhouse in #248
- Adjustments and improvements for LLMs by @alex-clickhouse in #250
- add review skill by @alex-clickhouse in #257
- Enable ParameterizedSelect_Null_ShouldReturnDbNull only from 26.5 by @alex-clickhouse in #258
- Add schema caching and manual config for inserts by @alex-clickhouse in #256
Full Changelog: 1.0.2...1.1.0
1.0.2
What's Changed
- Clean up and fill out dapper tests by @alex-clickhouse in #243
- fix query id reuse with batch inserts by @alex-clickhouse in #245
Full Changelog: 1.0.1...1.0.2
1.0.1
What's Changed
- Update RELEASENOTES.md by @alex-clickhouse in #222
- fix addparameter method by @alex-clickhouse in #224
- Bump Microsoft.Extensions.Configuration and Microsoft.Extensions.Configuration.Json by @dependabot[bot] in #230
- Bump Microsoft.Extensions.Diagnostics.HealthChecks from 10.0.2 to 10.0.3 by @dependabot[bot] in #231
- Bump Microsoft.Extensions.Http and Microsoft.Extensions.Logging.Abstractions by @dependabot[bot] in #232
- Add 26.2, remove 25.11 from test matrix by @alex-clickhouse in #233
- Fix broken codeql-bundle source by @alex-clickhouse in #234
- Obsolete serverversion by @alex-clickhouse in #235
- Bump actions/upload-artifact from 6 to 7 by @dependabot[bot] in #237
- Bump actions/download-artifact from 7 to 8 by @dependabot[bot] in #236
- Bump System.Text.Json from 10.0.2 to 10.0.3 by @dependabot[bot] in #241
- Bump Microsoft.Extensions.Logging.Console from 10.0.2 to 10.0.3 by @dependabot[bot] in #238
- Update README.md by @alex-clickhouse in #242
Full Changelog: 1.0.0...1.0.1
1.0.0
Documentation and Usage Examples:
Coinciding with the 1.0.0 release of the driver, we have greatly expanded the documentation and usage examples.
- Documentation: https://clickhouse.com/docs/integrations/csharp
- Usage examples: https://github.com/ClickHouse/clickhouse-cs/tree/main/examples
New: ClickHouseClient - Simplified Primary API
ClickHouseClient is the new recommended way to interact with ClickHouse. Thread-safe, singleton-friendly, and simpler than ADO.NET classes.
using var client = new ClickHouseClient("Host=localhost");| Method | Description |
|---|---|
ExecuteNonQueryAsync |
Execute DDL/DML (CREATE, INSERT, ALTER, DROP) |
ExecuteScalarAsync |
Return first column of first row |
ExecuteReaderAsync |
Stream results via ClickHouseDataReader |
InsertBinaryAsync |
High-performance bulk insert (replaces ClickHouseBulkCopy) |
ExecuteRawResultAsync |
Get raw result stream bypassing the parser |
InsertRawStreamAsync |
Insert from stream (CSV, JSON, Parquet, etc.) |
PingAsync |
Check server connectivity |
CreateConnection() |
Get ClickHouseConnection for ORM compatibility |
Per-query configuration via QueryOptions.
Parameters via ClickHouseParameterCollection:
var parameters = new ClickHouseParameterCollection();
parameters.Add("id", 42UL);
await client.ExecuteReaderAsync("SELECT * FROM t WHERE id = {id:UInt64}", parameters);Deprecation: ClickHouseBulkCopy is deprecated. Use client.InsertBinaryAsync(table, columns, rows) instead.
Breaking Changes:
-
Dropped support for .NET Framework and .NET Standard. The library now targets only
net6.0,net8.0,net9.0, andnet10.0. Removed support fornet462,net48, andnetstandard2.1. If you are using .NET Framework, you will need to stay on the previous version or migrate to .NET 6.0+. -
Removed feature discovery query from
OpenAsync. The connection'sOpenAsync()method no longer executesSELECT version()to discover server capabilities. This makes connection opening instantaneous (no network round-trip) but removes theSupportedFeaturesproperty fromClickHouseConnection. TheServerVersionproperty now throwsInvalidOperationException.Migration guidance: If you need to check the server version:
using var reader = await connection.ExecuteReaderAsync("SELECT version()"); reader.Read(); var version = reader.GetString(0);
-
DateTime reading behavior changed for columns without explicit timezone. Previously,
DateTimecolumns without a timezone (e.g.,DateTimevsDateTime('Europe/Amsterdam')) would use the server timezone (withUseServerTimezone=true) or client timezone to interpret the stored value. Now, these columns returnDateTimewithKind=Unspecified, preserving the wall-clock time exactly as stored without making assumptions about timezone.Column Type Old Behavior New Behavior DateTime(no timezone)Returned with server/client timezone applied DateTimewithKind=UnspecifiedDateTime('UTC')DateTimewithKind=UtcDateTimewithKind=Utc(unchanged)DateTime('Europe/Amsterdam')DateTimewithKind=UnspecifiedDateTimewithKind=Unspecified(unchanged). Reading as DateTimeOffset has correct offset applied.Migration guidance: If you need timezone-aware behavior, either:
- Use explicit timezones in your column definitions:
DateTime('UTC')orDateTime('Europe/Amsterdam') - Apply the timezone yourself after reading.
- Use explicit timezones in your column definitions:
-
DateTime writing now respects
DateTime.Kindproperty. Previously, allDateTimevalues were treated as wall-clock time in the target column's timezone regardless of theirKindproperty. The new behavior:DateTime.Kind Old Behavior New Behavior UtcTreated as wall-clock time in column timezone Preserved as-is (instant is maintained) LocalTreated as wall-clock time in column timezone Instant is maintained (inserted as UTC timestamp) UnspecifiedTreated as wall-clock time in column timezone Treated as wall-clock time in column timezone (unchanged) Migration guidance: If you were relying on the old behavior where UTC
DateTimevalues were reinterpreted in the column timezone, you should change these toDateTimeKind.Unspecified:// Old code (worked by accident): var utcTime = DateTime.UtcNow; // Would be reinterpreted in column timezone // New code (explicit intent): var wallClockTime = DateTime.SpecifyKind(myTime, DateTimeKind.Unspecified);
Important: When using parameters, you must specify the timezone in the parameter type hint to have string values interpreted in the column timezone:
command.AddParameter("dt", myDateTime); // Correct: timezone in type hint ensures proper interpretation command.CommandText = "INSERT INTO table (dt_column) VALUES ({dt:DateTime('Europe/Amsterdam')})"; // Gotcha: without timezone hint, UTC is used for interpretation command.CommandText = "INSERT INTO table (dt_column) VALUES ({dt:DateTime})"; // ^ String value interpreted in UTC, not column timezone!
This differs from bulk copy operations where the column timezone is known and used automatically.
-
Removed
UseServerTimezonesetting. This setting has been removed from the connection string,ClickHouseClientSettings, andClickHouseConnectionStringBuilder. It no longer has any effect since columns without timezones now returnUnspecifiedDateTime values without any timezone changes applied to what is returned from the server. -
Moved
ServerTimezoneproperty fromClickHouseConnectiontoClickHouseCommand. The server timezone is now available onClickHouseCommand.ServerTimezoneafter any query execution (the timezone is now extracted from theX-ClickHouse-Timezoneresponse header instead of requiring a separate query). -
Helper and extension methods made internal: DateTimeConversions, DataReaderExtensions, DictionaryExtensions, EnumerableExtensions, MathUtils, StringExtensions.
-
JSON writing default behavior changed. The default
JsonWriteModehas changed fromBinarytoString. This affects how JSON data is written to ClickHouse:Input Type Old Default (Binary) New Default (String) JsonObject/JsonNodeBinary encoding Serialized via JsonSerializer.Serialize()stringBinary encoding (parsed client-side) Passed through directly POCO (registered) Binary encoding with type hints Serialized via JsonSerializer.Serialize()POCO (unregistered) Exception Serialized via JsonSerializer.Serialize()Impact if you don't modify your code:
- JSON writing will still work, but uses string serialization instead of binary encoding; the JSON string will be parsed on the server instead of the client. This could lead to subtle changes in paths without type hints, e.g., values previously parsed as ints may be parsed as longs.
ClickHouseJsonPathandClickHouseJsonIgnoreattributes are ignored in String mode (they only work in Binary mode). Serialization happens viaSystem.Text.Json, so you can use those attributes instead.- Server setting
input_format_binary_read_json_as_string=1is automatically set when using String write mode
New Features/Improvements:
-
Automatic parameter type extraction from SQL. Types specified in the SQL query using
{name:Type}syntax are now automatically used for parameter formatting, eliminating the need to specify the type twice:// Before: type specified twice command.CommandText = "SELECT {dt:DateTime('Europe/Amsterdam')}"; command.AddParameter("dt", "DateTime('Europe/Amsterdam')", value); // After: type extracted from SQL automatically command.CommandText = "SELECT {dt:DateTime('Europe/Amsterdam')}"; command.AddParameter("dt", value);
The
AddParameter(name, type, value)overload is now marked obsolete. UseAddParameterWithTypeOverride()if you need to explicitly override the SQL type hint. -
POCO serialization support for JSON columns. When writing POCOs to JSON columns with typed hints (e.g.,
JSON(id Int64, name String)), the driver serializes properties using the hinted types for full type fidelity. Properties without a corresponding hinted path will have their ClickHouse types inferred automatically. Two attributes are available:[ClickHouseJsonPath("path")]for custom JSON paths and[ClickHouseJsonIgnore]to exclude properties. Property name matching to hint paths is case-sensitive (matching ClickHouse behavior which allows paths likeuserNameandUserNameto coexist). Register types viaclient.RegisterJsonSerializationType<T>(). -
JsonReadModeandJsonWriteModeconnection string settings for configurable JSON handling:JsonReadMode.Binary(default): ReturnsSystem.Text.Json.Nodes.JsonObjectJsonReadMode.String: Returns raw JSON string. Sets server settingoutput_format_binary_write_json_as_string=1.JsonWriteMode.String(default): AcceptsJsonObject,JsonNode, strings, and any object (serialized viaSystem.Text.Json.JsonSerializer). Sets server settinginput_format_binary_read_json_as_string=1.JsonWriteMode.Binary: Only accepts registered POCO types with full type...
1.0.0-rc2
What's Changed
- Adding more examples by @alex-clickhouse in #180
- fix typo in readme by @alex-clickhouse in #181
- Fully implement JSON binary writing, and add the ability to write directly from POCOs by @alex-clickhouse in #179
- Fix datetime parameter formating bug by @alex-clickhouse in #184
- Add JsonReadMode and JsonWriteMode settings for configurable JSON handling by @alex-clickhouse in #182
- Bump Microsoft.Extensions.Logging.Abstractions from 10.0.1 to 10.0.2 by @dependabot[bot] in #192
- Bump Microsoft.Extensions.Diagnostics.HealthChecks from 10.0.1 to 10.0.2 by @dependabot[bot] in #190
- Bump Microsoft.Extensions.Configuration and Microsoft.Extensions.Configuration.Json by @dependabot[bot] in #189
- More examples: geometry and table creation by @alex-clickhouse in #193
- Automatically call InitAsync() in BulkCopy by @alex-clickhouse in #186
- Make DI example clearer wrt connection and httpclient lifetime handling by @alex-clickhouse in #195
- Parameter parsing from query by @alex-clickhouse in #185
- Upserts example and examples restructuring by @alex-clickhouse in #196
- Change user agent key for the .net version by @alex-clickhouse in #197
- Expand writing type support for String/FixedString types and add ReadStringsAsByteArrays setting by @alex-clickhouse in #174
- Bump OpenTelemetry.Exporter.Console from 1.14.0 to 1.15.0 by @dependabot[bot] in #204
- Bump OpenTelemetry from 1.14.0 to 1.15.0 by @dependabot[bot] in #203
- Bump Microsoft.Extensions.Http from 10.0.1 to 10.0.2 by @dependabot[bot] in #200
- Bump Microsoft.Extensions.Logging.Console from 10.0.1 to 10.0.2 by @dependabot[bot] in #201
- Add 26.1 to test matrix, remove 25.10 by @alex-clickhouse in #199
- Remove support for net462, net48, netstandard21 by @alex-clickhouse in #194
- Add workflow_dispatch trigger to examples and tests workflows by @alex-clickhouse in #208
- Create codecov.yml by @alex-clickhouse in #206
- Refactor client structure by @alex-clickhouse in #219
- Bump Testcontainers.ClickHouse from 4.5.0 to 4.10.0 by @dependabot[bot] in #216
- Bump System.Text.Json from 10.0.1 to 10.0.2 by @dependabot[bot] in #215
Full Changelog: 1.0.0-rc1...1.0.0-rc2
1.0.0-rc1
What's Changed
- Add smart filter to examples runner by @alex-clickhouse in #110
- Adjust flaky test, sleep(0.3) usually takes < 300ms. by @alex-clickhouse in #112
- Add support for roles at connection and command levels by @alex-clickhouse in #113
- Update copilot-instructions.md by @alex-clickhouse in #114
- Create benchmark comparison workflow that runs a test of main vs the PR. by @alex-clickhouse in #115
- Generate query id on client side if not set by @alex-clickhouse in #116
- stop doing coverage on every test action by @alex-clickhouse in #117
- Bump actions/github-script from 7 to 8 by @dependabot[bot] in #119
- Bump NUnit.ConsoleRunner from 3.20.1 to 3.20.2 by @dependabot[bot] in #123
- Bump BenchmarkDotNet from 0.15.6 to 0.15.8 by @dependabot[bot] in #120
- Bump NUnit.Console and NUnit.ConsoleRunner by @dependabot[bot] in #122
- Fix crash when reading Map with duplicate keys by @alex-clickhouse in #124
- Add async insert examples by @alex-clickhouse in #125
- remove .net setup action, no longer necessary by @alex-clickhouse in #126
- Add support for JWT auth by @alex-clickhouse in #111
- Add support for custom headers by @alex-clickhouse in #128
- LLM instructions by @alex-clickhouse in #129
- Add InsertRawStreamAsync to connection for raw file inserts by @alex-clickhouse in #130
- [BREAKING] Make extensions internal by @verdie-g in #19
- Bump actions/cache from 4 to 5 by @dependabot[bot] in #133
- Bump NUnit.Console and NUnit.ConsoleRunner by @dependabot[bot] in #136
- Bump actions/upload-artifact from 5 to 6 by @dependabot[bot] in #134
- Bump actions/download-artifact from 6 to 7 by @dependabot[bot] in #132
- Bump linq2db from 6.0.0-rc.3 to 6.0.0 by @dependabot[bot] in #135
- Bump Microsoft.Extensions.Logging.Abstractions from 10.0.0 to 10.0.1 by @dependabot[bot] in #144
- Bump linq2db from 6.0.0 to 6.1.0 by @dependabot[bot] in #140
- Additional examples by @alex-clickhouse in #145
- Add support for QBit data type by @alex-clickhouse in #99
- Update bulk insert example by @alex-clickhouse in #147
- xml docs improvements by @alex-clickhouse in #148
- Bump Microsoft.Extensions.Configuration and Microsoft.Extensions.Configuration.Json by @dependabot[bot] in #142
- Bump NodaTime from 3.2.2 to 3.2.3 by @dependabot[bot] in #151
- Bump Microsoft.Extensions.Http from 10.0.0 to 10.0.1 by @dependabot[bot] in #149
- Bump Microsoft.Extensions.Logging.Console from 10.0.0 to 10.0.1 by @dependabot[bot] in #150
- Bump NUnit.Console and NUnit.ConsoleRunner by @dependabot[bot] in #152
- Add max_dynamic_paths=0 tests by @alex-clickhouse in #154
- Revert RELEASENOTES.md by @alex-clickhouse in #155
- feat(examples): add ASP.NET health checks example by @alex-clickhouse in #156
- Adjust datetime handling and add tests by @alex-clickhouse in #153
- Add claude folder to gitignore by @alex-clickhouse in #158
- Remove feature discovery query from OpenAsync by @alex-clickhouse in #157
- Add PingAsync method to ClickHouseConnection by @alex-clickhouse in #159
- Bump OpenTelemetry from 1.12.0 to 1.14.0 by @dependabot[bot] in #160
- Bump System.Text.Json from 9.0.10 to 10.0.1 by @dependabot[bot] in #161
- Warning fixes by @alex-clickhouse in #162
- Bump NUnit.Console and NUnit.ConsoleRunner by @dependabot[bot] in #164
- fix qbit tests on cloud by @alex-clickhouse in #167
- Sanitize env values in user agent string by @alex-clickhouse in #169
- Add 25.12 to test matrix by @alex-clickhouse in #171
- Add support for mid-stream exception detection via X-ClickHouse-Exception-Tag header by @alex-clickhouse in #168
- Cleanup, minor fixes, xml docs by @alex-clickhouse in #172
- Update RELEASENOTES.md by @alex-clickhouse in #173
- Add test naming guidelines to claude.md by @alex-clickhouse in #176
- add codeowners by @mshustov in #177
- Re-enable variant tests by @alex-clickhouse in #178
New Contributors
Full Changelog: 0.9.0...1.0.0-rc1
0.9.0
v0.9.0
Breaking Changes:
- FixedString is now returned as byte[] rather than String. FixedStrings are not necessarily valid UTF-8 strings, and the string transformation caused loss of information in some cases. Use Encoding.UTF8.GetString() on the resulting byte[] array to emulate the old behavior. String can still be used as a parameter or when inserting using BulkCopy into a FixedString column. When part of a json object, FixedString is still returned as a string.
- Removed obsolete MySQL compatibility mapping TIME -> Int64.
- Json serialization of bool arrays now uses the Boolean type instead of UInt8 (it is now consistent with how bool values outside arrays were handled).
- GEOMETRY is no longer an alias for String.
New Features/Improvements:
- Sessions can now be used with custom HttpClient or HttpClientFactory. Previously this combination was not allowed. Note that when sessions are enabled, ClickHouseConnection will allow only one request at a time, and responses are fully buffered before returning to ensure proper request serialization.
- Added support for BFloat16. It is converted to and from a 32-bit float.
- Added support for Time and Time64, which are converted to and from TimeSpan. The types are available since ClickHouse 25.6 and using them requires the enable_time_time64_type flag to be set.
- The Dynamic type now offers full support for all underlying types.
- Added support for LineString and MultiLineString geo types.
- Added support for the Geometry type, which can hold any geo subtype (Point, Ring, LineString, Polygon, MultiLineString, MultiPolygon). Available since ClickHouse 25.11. Requires allow_suspicious_variant_types to be set to 1.
- Json support has been improved in many ways:
- Now supports parsing Json that includes Maps; they are read into JsonObjects.
- Added support for decoding BigInteger types, UUID, IPv4, IPv6, and ClickHouseDecimal types (they are handled as strings).
- Expanded binary parsing to cover all types.
- Improved handling of numeric types when writing Json using BulkCopy: now properly detects and preserves Int32/In64 in addition to double (previously all numeric types were handled as double).
- Parsing null values in arrays is now handled properly.
- ClickHouseConnection.ConnectionString can now be set after creating the connection, to support cases where passing the connection string to the constructor is not possible.
- ClickHouseConnection.CreateCommand() now has an optional argument for the command text.
- Fixed a NullReferenceException when adding a parameter with null value and no provided type. The driver now simply sends '\N' (null value special character) when encountering this scenario.
Bug Fixes:
- Fixed a bug where serializing to json with an array of bools with both true and false elements would fail.
0.8.1
What's Changed
- Nuget readme fix by @alex-clickhouse in #82
- Update RELEASENOTES.md by @alex-clickhouse in #83
Full Changelog: 0.8.0...0.8.1
0.8.0
v0.8.0
Breaking Changes:
- Trying to set ClickHouseConnection.ConnectionString will now throw a NotSupportedException. Create a new connection with the desired settings instead.
- When a default database is not provided, the client no longer uses "default" (now uses empty string). This allows default user database settings to function as expected.
- ClickHouseDataSource.Logger (ILogger) property has been removed.
- Removed support for loading configuration from environment variables (CLICKHOUSE_DB, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD). Use connection strings or ClickHouseClientSettings instead.
- The default PooledConnectionIdleTimeout has been changed to 5 seconds, to prevent issues with half-open connections when using ClickHouse Cloud (where the default server-side idle timetout is 10s).
New Features/Improvements:
- Added .NET 10 as a target.
- The NuGet package is now signed.
- Enabled strong naming for the library.
- Added a new way to configure ClickHouseConnection: the ClickHouseClientSettings class. You can initialize it from a connection string, or simply by setting its properties.
- Added settings validation to prevent incorrect configurations.
- Added logging in the library, enable it by passing a LoggerFactory through the settings. Logging level configuration is configured through the factory. For more info, see the documentation: https://clickhouse.com/docs/integrations/csharp#logging-and-diagnostics
- Added EnableDebugMode setting to ClickHouseClientSettings for low-level .NET network tracing (.NET 5+). When enabled, traces System.Net events (HTTP, Sockets, DNS, TLS) to help diagnose network issues. Requires ILoggerFactory with Trace-level logging enabled. WARNING: Significant performance impact - not recommended for production use.
- AddClickHouseDataSource now automatically injects ILoggerFactory from the service provider when not explicitly provided.
- Improvements to ActivitySource for tracing: stopped adding tags when it was not necessary (thanks to @verdie-g), and made it configurable through ClickHouseDiagnosticsOptions.
- Added new AddClickHouseDataSource extension methods that accept ClickHouseClientSettings for strongly-typed configuration in DI scenarios.
- Added new AddClickHouseDataSource extension method that accepts IHttpClientFactory for better DI integration.
- Optimized response header parsing.
- Added list type conversion, so List can now be passed to the library (converts to Array() in ClickHouse). Thanks to @jorgeparavicini.
- Optimized EnumType value lookups.
- Avoid unnecessarily parsing the X-ClickHouse-Summary headers twice. Thanks to @verdie-g.
- Added the ability to pass a query id to ClickHouseConnection.PostStreamAsync(). Thanks to @dorki.
- The user agent string now also contains information on the host operating system, .NET version, and processor architecture.
Bug fixes: