-
ClickHouseClient(推奨) : シングルトンとしての利用を想定して設計された、高水準でスレッドセーフなクライアントです。クエリと一括挿入のためのシンプルな非同期 API を提供します。ほとんどのアプリケーションに最適です。 -
ADO.NET (
ClickHouseDataSource,ClickHouseConnection,ClickHouseCommand): 標準的な .NET のデータベース抽象化です。ORM インテグレーション (Dapper、Linq2db) や、ADO.NET 互換性が必要な場合に必須です。ClickHouseBulkCopyは、ADO.NET 接続を使用してデータを効率的に挿入するためのヘルパークラスです。ClickHouseBulkCopyは非推奨であり、今後のリリースで削除される予定です。代わりにClickHouseClient.InsertBinaryAsyncを使用してください。
移行ガイド
.csprojファイルで、パッケージ名を新しいClickHouse.Driverに変更し、NuGet の最新バージョン を指定します。- コードベース内の
ClickHouse.Clientへの参照をすべてClickHouse.Driverに更新します。
サポート対象の .NET バージョン
ClickHouse.Driver は、以下の .NET バージョンをサポートしています。
- .NET 6.0
- .NET 8.0
- .NET 9.0
- .NET 10.0
インストール
クイックスタート
設定
- 接続文字列: ホスト、認証情報、その他の接続オプションを指定する、セミコロン区切りのキーと値のペアです。
ClickHouseClientSettingsobject: 設定ファイルから読み込むことも、コード内で設定することもできる、厳密に型付けされた設定オブジェクトです。
接続設定
データフォーマットとシリアライゼーション
セッション管理
UseSession フラグを有効にすると、サーバー側セッションの状態が保持され、SET ステートメントや一時テーブルを利用できるようになります。セッションは 60 秒間非アクティブな状態が続くとリセットされます (デフォルトのタイムアウト) 。セッションの有効期間は、ClickHouse ステートメントまたはサーバー設定でセッション設定を指定することで延長できます。通常、ClickHouseConnection クラスでは並列動作が可能で、複数のスレッドからクエリを同時実行できます。ただし、UseSession フラグを有効にすると、1 つの接続で同時に実行できるアクティブなクエリは常に 1 つに制限されます (これはサーバー側の制約です) 。セキュリティ
HTTP クライアントの構成
ログとデバッグ
カスタム設定とロール
接続文字列でカスタム設定を指定する場合は、
set_ プレフィックスを使用します。たとえば "set_max_threads=4" のように指定します。ClickHouseClientSettings オブジェクトを使用する場合は、set_ プレフィックスは使用しません。使用可能な設定の一覧については、こちらを参照してください。接続文字列の例
基本接続
カスタムのClickHouse設定を使用する場合
QueryOptions
QueryOptions を使用すると、クライアント レベルの設定をクエリごとに上書きできます。すべてのプロパティは省略可能で、指定した場合にのみクライアントのデフォルト値を上書きします。
例:
InsertOptions
InsertOptions は、InsertBinaryAsync による一括 insert 操作に固有の設定を追加して、QueryOptions を拡張したものです。
QueryOptions のすべてのプロパティは、InsertOptions でも利用できます。
例:
スキーマプローブクエリのスキップ
InsertBinaryAsync は各 insert の前に SELECT ... WHERE 1=0 クエリを送信し、カラムの型を特定します。高スループットが求められる場合は、2 つの方法でこのオーバーヘッドをなくせます。
オプション 1: カラム型を明示的に指定する
コンパイル時点でテーブルのスキーマがわかっている場合は、ColumnTypes で直接指定します。これにより、スキーマプローブクエリは一切送信されません。
UseSchemaCache = true を設定すると、スキーマのクエリは最初の 1 回だけで済み、同じ ClickHouseClient インスタンスでの以降の insert に再利用されます:
ColumnTypesはUseSchemaCacheより優先されます。両方が設定されている場合は、明示的に指定した型が使用されます。- スキーマ cache では
ALTER TABLEによる変更は検出されません。テーブルのスキーマを変更した場合は、新しいClickHouseClientを作成するか、そのテーブルではUseSchemaCacheを使用しないでください。 - cache は
ClickHouseClientインスタンス単位で管理され、キーは (database, table) です。同じテーブル上の異なるカラムのサブセットでは、1 つのキャッシュ済みスキーマが共有されます。
ClickHouseClient
ClickHouseClient は、ClickHouse と連携するための推奨 API です。スレッドセーフで、シングルトンとして利用することを前提に設計されており、HTTP 接続プーリングも内部で管理します。
クライアントの作成
ClickHouseClientSettings オブジェクトを使用して、ClickHouseClient を作成します。利用可能なオプションについては、Configuration セクションを参照してください。
ClickHouse Cloud サービスの詳細は、ClickHouse Cloud コンソールで確認できます。
サービスを選択し、Connect をクリックします。
C# を選択します。接続情報が下に表示されます。
セルフマネージドの ClickHouse を使用している場合、接続情報は ClickHouse 管理者が設定します。
接続文字列を使用する場合:
ClickHouseClientSettings を使用します。
IHttpClientFactory を使用します。
ClickHouseClient は長期間の利用を前提としており、アプリケーション全体で共有して使うように設計されています。一度だけ作成し (通常はシングルトンとして) 、すべてのデータベース操作で再利用してください。クライアントは内部で HTTP 接続プーリングを管理します。クエリの実行
ExecuteNonQueryAsync を使用します:
ExecuteScalarAsync を使用します:
データの挿入
パラメーター化された挿入
ExecuteNonQueryAsync を使用して、パラメーター化クエリでデータを挿入します。パラメーターの型は、SQL 内で {name:Type} 構文を使って指定する必要があります。
一括挿入
InsertBinaryAsync を使用します。これは ClickHouse のネイティブな行バイナリ形式でデータをストリーミングし、バッチの並列アップロードをサポートするとともに、パラメーター化クエリで発生することがある「URL が長すぎる」エラーを回避します。
InsertOptions を使用してバッチ処理と並列度を設定します:
- クライアントは挿入前に
SELECT * FROM <table> WHERE 1=0を実行して、テーブル構造を自動的に取得します。指定する値は、対象カラムの型と一致している必要があります。このクエリを省略するには、InsertOptions.ColumnTypesまたはInsertOptions.UseSchemaCacheを使用してください。 MaxDegreeOfParallelism > 1の場合、バッチは並列にアップロードされます。セッションは並列挿入に対応していないため、セッションを無効にするか、MaxDegreeOfParallelism = 1に設定してください。- 指定していないカラムに対してサーバーが DEFAULT 値を適用するようにするには、
InsertOptions.FormatでRowBinaryFormat.RowBinaryWithDefaultsを使用してください。
POCO の挿入
object[] 配列を組み立てる代わりに、厳密に型付けされた POCO オブジェクトを直接 insert できます。型を一度登録したら、あとは IEnumerable<T> を渡します:
マップされたすべてのプロパティで
Type が明示的に指定されている場合、スキーマプローブクエリは完全にスキップされます。一部のプロパティにしか明示的な型が指定されていない場合、ドライバーはカラム一式に対するスキーマプローブにフォールバックします。
InsertBinaryAsync<T> は、object[] オーバーロードと同じ InsertOptions (バッチ化、並列度、スキーマキャッシュ) をサポートします。
object[] オーバーロードとは異なり、InsertBinaryAsync<T> では明示的なカラムリストを指定できません。カラムは、登録された型のマップ済みプロパティに基づいて決定されます。挿入するカラムを制御するには、[ClickHouseNotMapped] を使ってプロパティを除外するか、[ClickHouseColumn(Name = "...")] を使って名前を変更します。InsertOptions で ColumnTypes が設定されている場合は、POCO 属性よりそちらが優先されます。スキーマ進化
DEFAULT (またはその他のデフォルト式) を持つ新しいカラムはサーバー側で自動的に補完されます。コードを変更したり、再登録したりする必要はありません。
データの読み取り
ExecuteReaderAsync を使用します。返される ClickHouseDataReader では、GetInt64()、GetString()、GetFieldValue<T>() などのメソッドを使って、結果カラムに型付きでアクセスできます。
次の行に進むには Read() を呼び出します。これ以上行がない場合は false を返します。カラムには、インデックス (0 始まり) またはカラム名でアクセスできます。
SQLパラメータ
{parameter_name:DataType} です。
例:
SQL の’bind’ パラメータは HTTP URI のクエリパラメータとして渡されるため、数が多すぎると “URL が長すぎる” 例外が発生することがあります。この制限を回避してデータを一括挿入するには、
InsertBinaryAsync を使用してください。クエリ ID
query_id が割り当てられます。これは、system.query_log テーブルからデータを取得したり、長時間実行中のクエリをキャンセルしたりする際に使用できます。QueryOptions でカスタムのクエリ ID を指定することもできます。
カスタム パラメータ型対応
@ 形式のパラメータ (例: WHERE id = @id) を使用すると、ドライバーは .NET の値型から ClickHouse の型を自動的に推論します。たとえば、int は Int32 に、DateTime は DateTime にマッピングされます。
これらの既定の対応を上書きするには、ClickHouseClientSettings で ParameterTypeResolver を設定します。これは、個々のパラメータごとに ClickHouseType を設定しなくても、すべての DateTime パラメータでミリ秒精度の DateTime64(3) を使いたい場合や、すべての decimal で特定の小数点以下桁数を使いたい場合に便利です。
シンプルな型マッピングに DictionaryParameterTypeResolver を使用する:
IParameterTypeResolver:
値や名前に基づいて解決する場合は、IParameterTypeResolver インターフェイスを直接実装します。既定の推論に委ねるには、null を返します。
QueryOptions.ParameterTypeResolver を介してリゾルバを設定することもできます。設定した場合、クライアントレベルのリゾルバより優先されます。
型解決の優先順位:
リゾルバは優先順位チェーンの一要素です。優先度の高いものから低いものの順に示すと、次のとおりです。
- パラメータに明示的に設定された
ClickHouseType - クエリ内の
{name:Type}構文による SQL の型ヒント IParameterTypeResolver(QueryOptions.ParameterTypeResolverを使用し、未設定の場合はClickHouseClientSettings.ParameterTypeResolverにフォールバック)- 組み込みの型推論 (
TypeConverter.ToClickHouseType)
ClickHouseConnection パスでも機能します。設定は、クライアントから作成された接続に引き継がれます。
生データのストリーミング
ExecuteRawResultAsync を使用します。これは、データをファイルにエクスポートしたり、他のシステムにそのまま渡したりする場合に便利です:
JSONEachRow, CSV, TSV, Parquet, Native。利用可能なオプションについては、フォーマットのドキュメントを参照してください。
Raw ストリームの挿入
InsertRawStreamAsync を使用すると、CSV、JSON、Parquet など、または ClickHouse でサポートされている任意のフォーマットのデータを、ファイルストリームまたはメモリストリームから直接挿入できます。
CSVファイルから挿入する:
データ取り込みの動作を制御するオプションについては、フォーマット設定のドキュメントを参照してください。
その他の例
ADO.NET
ClickHouseConnection、ClickHouseCommand、ClickHouseDataReader を通じて、ADO.NET を完全にサポートしています。この API は、ORM インテグレーション (Dapper、Linq2db) や、標準的な .NET のdatabase 抽象化が必要な場合に不可欠です。
ClickHouseDataSource によるライフタイム管理
ClickHouseDataSource から作成してください。 DataSource は内部で単一の ClickHouseClient を管理しており、すべての接続はその HTTP 接続プールを共有します。
ClickHouseCommand の使用
ExecuteNonQueryAsync()- INSERT、UPDATE、DELETE、DDL ステートメントに使用しますExecuteScalarAsync()- 最初の行の最初のカラムを返しますExecuteReaderAsync()- 結果を反復処理するためのClickHouseDataReaderを返します
ClickHouseDataReader の使用
ClickHouseDataReader を使用すると、クエリ結果に型付きでアクセスできます。
ベストプラクティス
接続の有効期間とプーリング
ClickHouse.Driver は内部で System.Net.Http.HttpClient を使用しています。HttpClient にはエンドポイントごとの接続プールがあります。そのため、次の点に注意してください。
- データベースセッションは、接続プールで管理される HTTP 接続を介して多重化されます。
- HTTP 接続はプールによって自動的に再利用されます。
ClickHouseClientまたはClickHouseConnectionオブジェクトを破棄した後でも、接続が維持される場合があります。
DateTime の扱い
-
可能な限り UTC を使用します。 タイムスタンプは
DateTime('UTC')カラムとして保存し、コードではDateTimeKind.Utcを使用します。これにより、タイムゾーンの曖昧さを排除できます。 -
タイムゾーンを明示的に扱うには
DateTimeOffsetを使用します。DateTimeOffsetは常に特定の時点を表し、オフセット情報を含みます。 -
SQL の型ヒントでタイムゾーンを指定します。
Unspecifiedの DateTime 値を持つパラメーターを使用して非 UTC カラムを対象とする場合は、SQL にタイムゾーンを含めます。
非同期 INSERT
CustomSettings または接続文字列で非同期 INSERT を有効にします:
wait_for_async_insert で制御) :
主な設定:
セッション
- 一時テーブル (
CREATE TEMPORARY TABLE) - 複数のステートメントにまたがってクエリコンテキストを維持する
- セッションレベルの設定 (
SET max_threads = 4)
サポートされているデータ型
ClickHouse.Driver は、ClickHouse のすべてのデータ型をサポートしています。以下の表は、データベースからデータを読み取る際の ClickHouse の型とネイティブの .NET 型の対応関係を示しています。
型マッピング: ClickHouseから読み取る場合
整数型
浮動小数点型
Decimal 型
Decimal 型の変換は UseCustomDecimals 設定で制御されます。
Boolean 型
String 型
デフォルトでは、
String と FixedString(N) の両方のカラムは string として返されます。代わりに byte[] として読み取るには、接続文字列で ReadStringsAsByteArrays=true を設定します。これは、有効な UTF-8 でない可能性があるバイナリデータを保存する場合に便利です。日付と時刻の型
ClickHouse では、
DateTime と DateTime64 の値は内部的に Unix timestamp (epoch からの秒、またはその下位単位) として保存されます。保存は常に UTC ですが、カラムにはタイムゾーンを関連付けることができ、これによって値の表示方法や解釈方法が変わります。
DateTime の値を読み取る際、DateTime.Kind プロパティはカラムのタイムゾーンに基づいて設定されます。
UTC 以外のカラムでは、返される
DateTime はそのタイムゾーンでのローカル時刻を表します。そのタイムゾーンに対する正しいオフセットを持つ DateTimeOffset を取得するには、ClickHouseDataReader.GetDateTimeOffset() を使用してください。
DateTime('Europe/Amsterdam') ではなく DateTime) については、ドライバーは Kind=Unspecified の DateTime を返します。これにより、タイムゾーンについて何も仮定せず、保存されている時刻の値をそのまま正確に保持できます。
明示的なタイムゾーンを持たないカラムでタイムゾーンを考慮した動作が必要な場合は、次のいずれかを行ってください。
- カラム定義で明示的なタイムゾーンを使用する:
DateTime('UTC')またはDateTime('Europe/Amsterdam') - 読み取り後に自分でタイムゾーンを適用する。
JSON 型
JSON カラムの戻り値の型は、
JsonReadMode 設定で制御されます。
-
Binary(デフォルト):System.Text.Json.Nodes.JsonObjectを返します。JSON データを構造化された形で扱えますが、特殊な ClickHouse 型 (IP アドレス、UUID、高精度の Decimal 値など) は、JSON 構造内では文字列表現に変換されます。 -
String: 生の JSON をstringとして返します。ClickHouse の JSON 表現をそのまま保持できるため、JSON をパースせずにそのまま受け渡したい場合や、デシリアライゼーションを自分で処理したい場合に便利です。
その他の型
Dynamic 型と Variant 型は、各行で実際に使用されている基底型に対応する型に変換されます。
ジオメトリ型
Geometry 型は、任意のジオメトリ型を保持できる Variant 型で、対応する型に変換されます。
型マッピング: ClickHouse への書き込み
整数型
浮動小数点型
ブール型
文字列型
日付と時刻の型
ドライバーは値の書き込み時に
DateTime.Kind を考慮します。
DateTimeOffset の値では、常に正確な時点が保持されます。
例: UTC DateTime (時点は保持される)
DateTimeKind.Utc または DateTimeOffset を使用してください。これにより、サーバーのタイムゾーン、クライアントのタイムゾーン、またはカラムのタイムゾーンに関係なく、コードが常に一貫して動作します。
HTTP パラメータと Bulk Copy の違い
Unspecified の DateTime 値を書き込む際、HTTP パラメータのバインドと Bulk Copy には重要な違いがあります。
Bulk Copy は対象カラムのタイムゾーンを認識しており、そのタイムゾーンで Unspecified の値を正しく解釈します。
HTTP Parameters はカラムのタイムゾーンを自動的には認識しません。SQL の型ヒントでそのタイムゾーンを指定する必要があります。
Decimal 型
JSON 型
JSON の書き込み時の動作は、
JsonWriteMode 設定で制御されます。
-
String(デフォルト):string、JsonObject、JsonNode、または任意のオブジェクトを受け付けます。すべての入力はSystem.Text.Json.JsonSerializerでシリアライズされ、サーバー側でパースするために JSON 文字列として送信されます。これは最も柔軟なモードで、型登録なしで動作します。 -
Binary: 登録済みの POCO 型のみを受け付けます。データはクライアント側で、完全な型ヒントのサポート付きで ClickHouse のバイナリ JSON フォーマットに変換されます。使用する前にconnection.RegisterJsonSerializationType<T>()を呼び出す必要があります。このモードでstringまたはJsonNodeの値を書き込むと、ArgumentExceptionがスローされます。
型付き JSON カラム
JSON(id UInt64, price Decimal128(2))) がある場合、ドライバーはそれらのヒントを使って、値を型情報を完全に保ったままシリアライズします。これにより、UInt64、Decimal、UUID、DateTime64 など、汎用的な JSON としてシリアライズすると精度が失われる可能性のある型でも、精度を保持できます。
POCO のシリアライゼーション
JsonWriteMode に応じて 2 つの方法で JSON カラムに書き込めます。
String mode (default): POCO は System.Text.Json.JsonSerializer によってシリアライズされます。型の登録は不要です。最もシンプルな方法で、匿名オブジェクトでも使用できます。
Binary mode: POCO は、型ヒントを完全にサポートするドライバーのバイナリ JSON フォーマットを使用してシリアライズされます。使用前に connection.RegisterJsonSerializationType<T>() で型を登録する必要があります。このモードでは、属性を使ったカスタムパスマッピングをサポートします。
-
[ClickHouseJsonPath("path")]: プロパティをカスタム JSON パスにマッピングします。ネストされた structure や、プロパティ名が目的の JSON キーと異なる場合に便利です。Binary mode でのみ機能します。 -
[ClickHouseJsonIgnore]: プロパティをシリアライゼーションの対象から除外します。Binary mode でのみ機能します。
UserId は、userid ではなく、UserId と定義されたヒントにのみ一致します。これは、userName と UserName のようなパスを別個のフィールドとして共存させられる ClickHouse の動作と一致しています。
制限事項 (Binary mode のみ) :
- POCO 型は、シリアライズする前に
connection.RegisterJsonSerializationType<T>()を使用してコネクションに登録しておく必要があります。未登録の型をシリアライズしようとすると、ClickHouseJsonSerializationExceptionがスローされます。 - Dictionary および配列/リストのプロパティを正しくシリアライズするには、カラム定義に型ヒントが必要です。ヒントがない場合は、代わりに String mode を使用してください。
- POCO プロパティの null 値は、カラム定義内のパスに
Nullable(T)型ヒントがある場合にのみ書き込まれます。ClickHouse では動的 JSON パス内でNullable型は使用できないため、ヒントのない null プロパティはスキップされます。 ClickHouseJsonPath属性とClickHouseJsonIgnore属性は String mode では無視されます (有効なのは Binary mode のみです) 。
その他の型
ジオメトリ型
書き込みではサポートされていません
ネスト型の扱い
Nested(...)) は、配列として読み書きできます。
ログと診断
Microsoft.Extensions.Logging の抽象化レイヤーと統合されており、軽量で必要に応じて有効化できるログ機能を提供します。有効にすると、ドライバーは接続ライフサイクル イベント、コマンド実行、トランスポート処理、バルク挿入操作に関する構造化メッセージを出力します。ログ機能は完全に任意であり、ロガーを設定していないアプリケーションも追加のオーバーヘッドなしでそのまま動作し続けます。
クイックスタート
appsettings.json を使用する
インメモリ構成を使用する
カテゴリと出力元
例: 接続の問題を診断する
- HTTP クライアント ファクトリの選択 (既定のプールまたは単一接続)
- HTTP ハンドラーの設定 (SocketsHttpHandler または HttpClientHandler)
- 接続プールの設定 (MaxConnectionsPerServer、PooledConnectionLifetime など)
- タイムアウトの設定 (ConnectTimeout、Expect100ContinueTimeout など)
- SSL/TLS の設定
- 接続のオープン/クローズ イベント
- セッション ID の追跡
デバッグモード: ネットワークトレースと診断
ClickHouse.Driver.Diagnostic.TraceHelper クラスを使って手動で有効にします) 。イベントは ClickHouse.Driver.NetTrace カテゴリにログ出力されます。警告: これにより非常に大量の logs が生成され、パフォーマンスに影響します。本番環境でデバッグモードを有効にすることは推奨されません。
OpenTelemetry
System.Diagnostics.Activity API を通じて、OpenTelemetry の分散トレーシングをネイティブにサポートしています。有効にすると、ドライバーはデータベース操作に対するスパンを出力し、それらを Jaeger や ClickHouse 自体 (OpenTelemetry Collector 経由) などのオブザーバビリティバックエンドにエクスポートできます。
トレーシングを有効にする
ActivitySource を OpenTelemetry の設定に追加します。
スパン属性
設定オプション
ClickHouseDiagnosticsOptions を使用して、トレーシングの動作を制御します。
TLS 設定
カスタム証明書の検証
ServerCertificateCustomValidationCallback ハンドラーを構成した独自の HttpClient を指定します。
カスタム HttpClient を指定する際の注意事項
- 自動圧縮解除: 圧縮が無効になっていない場合は、
AutomaticDecompressionを有効にする必要があります (圧縮はデフォルトで有効です) 。 - アイドルタイムアウト: ハーフオープン接続による接続エラーを避けるため、
PooledConnectionIdleTimeoutはサーバーのkeep_alive_timeout(ClickHouse Cloud では 10 秒) より短く設定してください。
ORM サポート
ClickHouseConnection) が必要です。接続のライフサイクルを適切に管理するため、ClickHouseDataSource から接続を作成してください。
Dapper
ClickHouse.Driver は Dapper に対応しています。ドライバーは、Dapper の @parameter 構文を ClickHouse のネイティブな {parameter:Type} 構文に自動変換し、型は .NET の値から推論されます。
適切に connection のライフタイムを管理するには、ClickHouseDataSource を使用します。
パラメーターの受け渡し形式
DynamicParameters (ディクショナリまたは匿名オブジェクトから) :
POCO へのクエリ
ClickHouseネイティブのパラメーター構文
Dictionary<string, object> を使用し、SQL 内で ClickHouse の {param:Type} 構文を直接使用してください。同じパラメーターに対して @param 構文と {param:Type} 構文を併用しないでください。
WHERE IN
WHERE id IN (@Ids1, @Ids2, @Ids3) に書き換え、ドライバーが展開された各パラメーターをそれぞれ変換します。
Array パラメーターを使った ClickHouse の has() も動作します:
カスタム型ハンドラー
ITuple、BigInteger、ClickHouseDecimal など、一部の ClickHouse の型では、起動時にハンドラーを登録する必要があります。
Dapper.Contrib
GetAll<T>() と Get<T>(id) は動作します。Insert<T>() は動作しません。これは SQL Server の構文 (SCOPE_IDENTITY、[]) を生成するためです。代わりに、ClickHouseClient のネイティブな InsertBinaryAsync メソッドを使用することを推奨します。
制限事項
Linq2db
DataConnection を作成します。
BulkCopyAsync を使用します。
Entity Framework Core
SaveChanges を通じてデータを insert できます。いずれも使い慣れた EF Core のパターンで行えます。
- NuGet:
ClickHouse.EntityFrameworkCore - Source: GitHub
このプロバイダーは現在も活発に開発が進められています。現行の release では、LINQ クエリ (JOIN、subqueries、set operations を含む) 、
SaveChanges / BulkInsertAsync による INSERT、完全な DDL (CREATE / ALTER / DROP) を伴う移行、そして ClickHouse 固有の table engine 設定をサポートしています。UPDATE / DELETE には対応していません。インストール
クイックスタート
DbContextを定義し、LINQ でクエリを実行します。
サポートされる型
Decimal128/Decimal256 カラムの完全な精度が必要な場合は、decimal ではなく ClickHouseDecimal (ClickHouse.Driver.Numerics のもの) を使用してください。.NET の decimal は有効桁数が 28~29 桁に制限されます。
サポートされている LINQ 操作
Where, OrderBy, Take, Skip, Select, First, Single, Any, All, Count, Distinct, AsNoTracking
GROUP BY と集計: Count, LongCount, Sum, Average, Min, Max を伴う GroupBy — HAVING (.GroupBy() の後に .Where() を使用) 、1 つのプロジェクション内での複数の集計、集計結果に対する OrderBy を含みます。
JOIN: Join (INNER) 、GroupJoin/SelectMany パターン (LEFT および CROSS) 。LEFT JOIN は、一致しない行に対して実際の null 値を返します (下記の LEFT JOIN の NULL セマンティクス を参照) 。
サブクエリ: 相関 Contains / IN、Any / EXISTS、All、およびプロジェクション内のスカラー サブクエリ。
集合演算: Concat (→ UNION ALL) 、Union (→ UNION DISTINCT) 、Intersect、Except。
インラインのローカルコレクション: インメモリコレクション (int[]、List<T> など) に対する join や Contains は、一連の UNION に変換されます。
文字列メソッド: Contains, StartsWith, EndsWith, IndexOf, Replace, Substring, Trim/TrimStart/TrimEnd, ToLower, ToUpper, Length, IsNullOrEmpty, Concat (および + 演算子) 。
数学関数: 標準の Math および MathF メソッドは、対応する ClickHouse の関数に変換されます — 算術、対数、三角、およびユーティリティ関数。
LEFT JOIN の NULL セマンティクス
set_join_use_nulls=1 を自動的に設定します。
ClickHouse サーバーまたは profile でこの設定の変更が禁止されている場合 (例: readonly=1 の profile) 、次のように無効化してください。
== null の代わりに、0 / "" との明示的な比較を使用してください。
データの挿入
SaveChanges では、ドライバーが提供するネイティブの InsertBinaryAsync API を使用します。RowBinary エンコーディングと GZip 圧縮を利用するため、パラメーター化 SQL よりもはるかに効率的です。
Added から Unchanged に変わります。
バッチサイズ は設定できます (デフォルトは 1000) :
一括挿入
SaveChanges ではなく BulkInsertAsync を使用してください。これは DbContext の拡張メソッドで、EF Core の変更トラッカー、ID 解決、状態管理を完全にバイパスし、RowBinary エンコーディングと GZip 圧縮を使用して、ドライバーの InsertBinaryAsync を直接呼び出します。
そのため、挿入後にエンティティの追跡が不要な大規模データセットの読み込みに適しています。
IEnumerable<T> を使用できます。エンティティはすべてをメモリに読み込むことなく順次処理されます。戻り値は挿入された行数です。挿入後もエンティティは DbContext にアタッチされないため、Added → Unchanged の状態遷移は発生しません。
列挙型
Enum8/Enum16 カラムは、string プロパティまたは C# の enum 型にマッピングできます。C# の列挙型を使用する場合、プロバイダーは列挙型とその文字列表現の間で自動的に変換します。
カスタム型の変換
ValueConverter システムを使うと、カスタム型をプロバイダーがすでにサポートしている型にマッピングできます。プロバイダーがカスタム型を直接扱うことはなく、EF Core がその境界で変換を行います。
プロパティ単位の変換:
カラム型のアノテーション
string、int、DateTime などのスカラー型では、プロバイダーが ClickHouse の型を自動的に推論します。パラメーター化された型やラッパーについては、ClickHouse の型を明示的に指定する必要があります。
データ アノテーション (属性) を使用する場合:
OnModelCreating で fluent API を使用する方法:
Array(Nullable(Int32)) や LowCardinality(Nullable(String)) のようなネストされたラッパー型をサポートしています — プロバイダーは Nullable と LowCardinality をどのネストレベルでも自動的にアンラップします。
Variant と Dynamic カラム
Variant(T1, T2, ...) カラムおよび Dynamic カラムは、.NET では object にマップされます。object は自動的な型推論には汎用的すぎるため、.HasColumnType() でストア型を明示的に指定する必要があります。
string、ulong、ulong[]) に自動的にデシリアライズされます。
JSON カラム
Json カラム型をサポートしており、System.Text.Json.Nodes.JsonNode (プライマリ) または string (自動 ValueConverter 使用時) に対応付けられます。
SaveChanges と BulkInsertAsync の両方で利用できます:
string として Json カラム型にマップしてください。プロバイダーが ValueConverter を自動的に適用します。
- JSON パスは変換されません — LINQ の
entity.Data["name"]は、ClickHouse のdata.nameという SQL 構文には変換されません。JSON 以外のカラムでフィルタし、JSON はメモリ上で確認してください。 - NULL セマンティクス — ClickHouse の JSON type は、NULL 値に対して SQL NULL ではなく
{}(空のオブジェクト) を返します。 - 整数の精度 — ClickHouse の JSON は、すべての整数を
Int64として格納します。JsonNode経由で読み取る場合は、GetValue<int>()ではなくGetValue<long>()を使用してください。
テーブルエンジン
ToTable(name, t => ...) のフルーエント API を使用して、ClickHouse テーブルのエンジンとエンジン固有の句を設定します。エンジンが設定されていない場合、プロバイダーは既定で MergeTree を使用し、ORDER BY はエンティティの主キーに基づいて決定されます。
エンジン句:
WithOrderBy, WithPartitionBy, WithPrimaryKey, WithSampleBy, WithTtl, WithSettings。いずれも HasXxxEngine() が返すエンジンビルダーに対して指定します。
カラムレベルの機能: HasCodec, HasTtl, HasComment, HasDefault — いずれも移行の対象になります。
データスキッピング索引 — HasIndex(...).HasSkippingIndexType(...) で指定します:
移行
移行の制限事項
移行以外にも、このプロバイダーはまだ以下をサポートしていません。
UPDATE/DELETE- トランザクション:
BeginTransactionは no-op です。ClickHouse は ACID トランザクションをサポートしていません。 - JSON パス クエリの変換: LINQ の
entity.Data["key"]は、ClickHouse のdata.keySQL 構文に変換されません。JSON 以外のカラムでフィルタリングし、JSON はメモリ上で確認してください。
制限事項
AggregateFunction カラム
AggregateFunction(...) 型のカラムは、直接クエリしたり、挿入したりすることはできません。
挿入するには: