メインコンテンツへスキップ
ClickHouse に接続するための公式 C# クライアントです。 クライアントのソースコードは GitHubリポジトリ で公開されています。 当初は Oleg V. Kozlyuk によって開発されました。 このライブラリは、主に 2 つの API を提供します。
  • ClickHouseClient (推奨) : シングルトンとしての利用を想定して設計された、高水準でスレッドセーフなクライアントです。クエリと一括挿入のためのシンプルな非同期 API を提供します。ほとんどのアプリケーションに最適です。
  • ADO.NET (ClickHouseDataSource, ClickHouseConnection, ClickHouseCommand): 標準的な .NET のデータベース抽象化です。ORM インテグレーション (Dapper、Linq2db) や、ADO.NET 互換性が必要な場合に必須です。ClickHouseBulkCopy は、ADO.NET 接続を使用してデータを効率的に挿入するためのヘルパークラスです。ClickHouseBulkCopy は非推奨であり、今後のリリースで削除される予定です。代わりに ClickHouseClient.InsertBinaryAsync を使用してください。
どちらの API も同じ基盤となる HTTP 接続プールを共有しており、同じアプリケーション内で併用できます。

移行ガイド

  1. .csproj ファイルで、パッケージ名を新しい ClickHouse.Driver に変更し、NuGet の最新バージョン を指定します。
  2. コードベース内の ClickHouse.Client への参照をすべて ClickHouse.Driver に更新します。

サポート対象の .NET バージョン

ClickHouse.Driver は、以下の .NET バージョンをサポートしています。
  • .NET 6.0
  • .NET 8.0
  • .NET 9.0
  • .NET 10.0

インストール

NuGet からパッケージをインストールします。
または、NuGet パッケージ マネージャーを使用します。

クイックスタート

設定

ClickHouse への接続を設定する方法は 2 つあります。
  • 接続文字列: ホスト、認証情報、その他の接続オプションを指定する、セミコロン区切りのキーと値のペアです。
  • ClickHouseClientSettings object: 設定ファイルから読み込むことも、コード内で設定することもできる、厳密に型付けされた設定オブジェクトです。
以下に、すべての設定項目、そのデフォルト値、およびそれぞれの動作への影響を一覧で示します。

接続設定

データフォーマットとシリアライゼーション

セッション管理

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 で直接指定します。これにより、スキーマプローブクエリは一切送信されません。
オプション 2: スキーマをキャッシュする 同じテーブルに繰り返し insert する場合は、UseSchemaCache = true を設定すると、スキーマのクエリは最初の 1 回だけで済み、同じ ClickHouseClient インスタンスでの以降の insert に再利用されます:
  • ColumnTypesUseSchemaCache より優先されます。両方が設定されている場合は、明示的に指定した型が使用されます。
  • スキーマ 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.FormatRowBinaryFormat.RowBinaryWithDefaults を使用してください。

POCO の挿入

object[] 配列を組み立てる代わりに、厳密に型付けされた POCO オブジェクトを直接 insert できます。型を一度登録したら、あとは IEnumerable<T> を渡します:
既定では、公開されているすべての読み取り可能なプロパティは、厳密な大文字と小文字の区別を伴う名前一致によりカラムにマッピングされます。属性を使用して、このマッピングをカスタマイズできます。
マップされたすべてのプロパティで Type が明示的に指定されている場合、スキーマプローブクエリは完全にスキップされます。一部のプロパティにしか明示的な型が指定されていない場合、ドライバーはカラム一式に対するスキーマプローブにフォールバックします。 InsertBinaryAsync<T> は、object[] オーバーロードと同じ InsertOptions (バッチ化、並列度、スキーマキャッシュ) をサポートします。
object[] オーバーロードとは異なり、InsertBinaryAsync<T> では明示的なカラムリストを指定できません。カラムは、登録された型のマップ済みプロパティに基づいて決定されます。挿入するカラムを制御するには、[ClickHouseNotMapped] を使ってプロパティを除外するか、[ClickHouseColumn(Name = "...")] を使って名前を変更します。InsertOptionsColumnTypes が設定されている場合は、POCO 属性よりそちらが優先されます。

スキーマ進化

型の登録後にターゲットテーブルへカラムが追加されても、POCO による insert はそのまま問題なく動作します。ドライバーが insert するのは POCO にマッピングされたカラムだけなので、DEFAULT (またはその他のデフォルト式) を持つ新しいカラムはサーバー側で自動的に補完されます。コードを変更したり、再登録したりする必要はありません。

データの読み取り

SELECT クエリの実行には ExecuteReaderAsync を使用します。返される ClickHouseDataReader では、GetInt64()GetString()GetFieldValue<T>() などのメソッドを使って、結果カラムに型付きでアクセスできます。 次の行に進むには Read() を呼び出します。これ以上行がない場合は false を返します。カラムには、インデックス (0 始まり) またはカラム名でアクセスできます。

SQLパラメータ

ClickHouse では、SQLクエリのクエリパラメータの標準的なフォーマットは {parameter_name:DataType} です。 例:
SQL の’bind’ パラメータは HTTP URI のクエリパラメータとして渡されるため、数が多すぎると “URL が長すぎる” 例外が発生することがあります。この制限を回避してデータを一括挿入するには、InsertBinaryAsync を使用してください。

クエリ ID

すべてのクエリには一意の query_id が割り当てられます。これは、system.query_log テーブルからデータを取得したり、長時間実行中のクエリをキャンセルしたりする際に使用できます。QueryOptions でカスタムのクエリ ID を指定することもできます。
カスタムの QueryId を指定する場合は、呼び出しごとに必ず一意になるようにしてください。ランダムな GUID を使うのが適切です。

カスタム パラメータ型対応

@ 形式のパラメータ (例: WHERE id = @id) を使用すると、ドライバーは .NET の値型から ClickHouse の型を自動的に推論します。たとえば、intInt32 に、DateTimeDateTime にマッピングされます。 これらの既定の対応を上書きするには、ClickHouseClientSettingsParameterTypeResolver を設定します。これは、個々のパラメータごとに ClickHouseType を設定しなくても、すべての DateTime パラメータでミリ秒精度の DateTime64(3) を使いたい場合や、すべての decimal で特定の小数点以下桁数を使いたい場合に便利です。 シンプルな型マッピングに DictionaryParameterTypeResolver を使用する:
高度な用途向けのカスタム IParameterTypeResolver: 値や名前に基づいて解決する場合は、IParameterTypeResolver インターフェイスを直接実装します。既定の推論に委ねるには、null を返します。
単一のクエリに対しては、QueryOptions.ParameterTypeResolver を介してリゾルバを設定することもできます。設定した場合、クライアントレベルのリゾルバより優先されます。 型解決の優先順位: リゾルバは優先順位チェーンの一要素です。優先度の高いものから低いものの順に示すと、次のとおりです。
  1. パラメータに明示的に設定された ClickHouseType
  2. クエリ内の {name:Type} 構文による SQL の型ヒント
  3. IParameterTypeResolver (QueryOptions.ParameterTypeResolver を使用し、未設定の場合は ClickHouseClientSettings.ParameterTypeResolver にフォールバック)
  4. 組み込みの型推論 (TypeConverter.ToClickHouseType)
このリゾルバは、ADO.NET の ClickHouseConnection パスでも機能します。設定は、クライアントから作成された接続に引き継がれます。

生データのストリーミング

データリーダーを介さず、特定のフォーマットでクエリ結果を直接ストリーミングするには、ExecuteRawResultAsync を使用します。これは、データをファイルにエクスポートしたり、他のシステムにそのまま渡したりする場合に便利です:
一般的なフォーマット: JSONEachRow, CSV, TSV, Parquet, Native。利用可能なオプションについては、フォーマットのドキュメントを参照してください。

Raw ストリームの挿入

InsertRawStreamAsync を使用すると、CSV、JSON、Parquet など、または ClickHouse でサポートされている任意のフォーマットのデータを、ファイルストリームまたはメモリストリームから直接挿入できます。 CSVファイルから挿入する:
データ取り込みの動作を制御するオプションについては、フォーマット設定のドキュメントを参照してください。

その他の例

さらに実践的な使用例については、GitHubリポジトリ内のexamplesディレクトリを参照してください。

ADO.NET

このライブラリは、ClickHouseConnectionClickHouseCommandClickHouseDataReader を通じて、ADO.NET を完全にサポートしています。この API は、ORM インテグレーション (Dapper、Linq2db) や、標準的な .NET のdatabase 抽象化が必要な場合に不可欠です。

ClickHouseDataSource によるライフタイム管理

適切なライフタイム管理と接続プーリングを確実に行うため、接続は必ず ClickHouseDataSource から作成してください。 DataSource は内部で単一の ClickHouseClient を管理しており、すべての接続はその HTTP 接続プールを共有します。
依存関係の挿入では:
本番環境のコードで ClickHouseConnection を直接作成しないでください。直接インスタンス化するたびに、新しい HTTP クライアントと接続プールが作成されるため、高負荷時にソケットが枯渇するおそれがあります。
代わりに、必ず ClickHouseDataSource を使用するか、単一の ClickHouseClient インスタンスを共有してください。

ClickHouseCommand の使用

SQL を実行するコマンドを接続から作成します。
コマンド メソッド:
  • ExecuteNonQueryAsync() - INSERT、UPDATE、DELETE、DDL ステートメントに使用します
  • ExecuteScalarAsync() - 最初の行の最初のカラムを返します
  • ExecuteReaderAsync() - 結果を反復処理するための ClickHouseDataReader を返します

ClickHouseDataReader の使用

ClickHouseDataReader を使用すると、クエリ結果に型付きでアクセスできます。

ベストプラクティス

接続の有効期間とプーリング

ClickHouse.Driver は内部で System.Net.Http.HttpClient を使用しています。HttpClient にはエンドポイントごとの接続プールがあります。そのため、次の点に注意してください。
  • データベースセッションは、接続プールで管理される HTTP 接続を介して多重化されます。
  • HTTP 接続はプールによって自動的に再利用されます。
  • ClickHouseClient または ClickHouseConnection オブジェクトを破棄した後でも、接続が維持される場合があります。
推奨パターン:
カスタムの HttpClient または HttpClientFactory を使用する場合は、半閉状態の接続によるエラーを避けるため、PooledConnectionIdleTimeout をサーバーの keep_alive_timeout より小さい値に設定してください。Cloud デプロイメントの既定の keep_alive_timeout は 10 秒です。
共有の HttpClient を使わずに、複数の ClickHouseClient や単独の ClickHouseConnection インスタンスを作成するのは避けてください。各インスタンスはそれぞれ独自の接続プールを作成します。

DateTime の扱い

  1. 可能な限り UTC を使用します。 タイムスタンプは DateTime('UTC') カラムとして保存し、コードでは DateTimeKind.Utc を使用します。これにより、タイムゾーンの曖昧さを排除できます。
  2. タイムゾーンを明示的に扱うには DateTimeOffset を使用します。 DateTimeOffset は常に特定の時点を表し、オフセット情報を含みます。
  3. SQL の型ヒントでタイムゾーンを指定します。 Unspecified の DateTime 値を持つパラメーターを使用して非 UTC カラムを対象とする場合は、SQL にタイムゾーンを含めます。

非同期 INSERT

非同期 INSERT では、バッチ化の責任がクライアントからサーバーに移ります。クライアント側でバッチ化する代わりに、サーバーが受信データをバッファに保持し、設定可能なしきい値に基づいてストレージに書き出します。これは、多数のエージェントが小さなペイロードを送信するオブザーバビリティのワークロードのような、高い同時実行性が求められるシナリオで有効です。 CustomSettings または接続文字列で非同期 INSERT を有効にします:
2 つのモード (wait_for_async_insert で制御) :
wait_for_async_insert=0 では、エラーはフラッシュ時にのみ表面化するため、元の insert までさかのぼって特定できません。また、クライアント側でバックプレッシャーもかからないため、サーバーの過負荷を招くおそれがあります。
主な設定:

セッション

セッションは、状態を保持するサーバー側の機能が必要な場合にのみ有効にしてください。例:
  • 一時テーブル (CREATE TEMPORARY TABLE)
  • 複数のステートメントにまたがってクエリコンテキストを維持する
  • セッションレベルの設定 (SET max_threads = 4)
セッションを有効にすると、同じセッションの同時使用を防ぐため、リクエストは直列化されます。そのため、セッション状態を必要としないワークロードではオーバーヘッドが発生します。
ADO.NET を使用する場合 (ORM との互換性のため) :

サポートされているデータ型

ClickHouse.Driver は、ClickHouse のすべてのデータ型をサポートしています。以下の表は、データベースからデータを読み取る際の ClickHouse の型とネイティブの .NET 型の対応関係を示しています。

型マッピング: ClickHouseから読み取る場合

整数型


浮動小数点型


Decimal 型

Decimal 型の変換は UseCustomDecimals 設定で制御されます。

Boolean 型


String 型

デフォルトでは、StringFixedString(N) の両方のカラムは string として返されます。代わりに byte[] として読み取るには、接続文字列で ReadStringsAsByteArrays=true を設定します。これは、有効な UTF-8 でない可能性があるバイナリデータを保存する場合に便利です。

日付と時刻の型

ClickHouse では、DateTimeDateTime64 の値は内部的に Unix timestamp (epoch からの秒、またはその下位単位) として保存されます。保存は常に UTC ですが、カラムにはタイムゾーンを関連付けることができ、これによって値の表示方法や解釈方法が変わります。 DateTime の値を読み取る際、DateTime.Kind プロパティはカラムのタイムゾーンに基づいて設定されます。 UTC 以外のカラムでは、返される DateTime はそのタイムゾーンでのローカル時刻を表します。そのタイムゾーンに対する正しいオフセットを持つ DateTimeOffset を取得するには、ClickHouseDataReader.GetDateTimeOffset() を使用してください。
明示的なタイムゾーンを 持たない カラム (つまり DateTime('Europe/Amsterdam') ではなく DateTime) については、ドライバーは Kind=UnspecifiedDateTime を返します。これにより、タイムゾーンについて何も仮定せず、保存されている時刻の値をそのまま正確に保持できます。 明示的なタイムゾーンを持たないカラムでタイムゾーンを考慮した動作が必要な場合は、次のいずれかを行ってください。
  1. カラム定義で明示的なタイムゾーンを使用する: DateTime('UTC') または DateTime('Europe/Amsterdam')
  2. 読み取り後に自分でタイムゾーンを適用する。

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 への書き込み

データの挿入時に、ドライバーは .NET 型を対応する ClickHouse 型に変換します。以下の表は、各 ClickHouse カラム型で受け入れ可能な .NET 型を示しています。

整数型


浮動小数点型


ブール型


文字列型


日付と時刻の型

ドライバーは値の書き込み時に DateTime.Kind を考慮します。 DateTimeOffset の値では、常に正確な時点が保持されます。 例: UTC DateTime (時点は保持される)
例: 未指定の DateTime (時計上の時刻)
推奨事項: 最もシンプルで予測しやすい動作にするため、すべての DateTime 操作で DateTimeKind.Utc または DateTimeOffset を使用してください。これにより、サーバーのタイムゾーン、クライアントのタイムゾーン、またはカラムのタイムゾーンに関係なく、コードが常に一貫して動作します。

HTTP パラメータと Bulk Copy の違い

Unspecified の DateTime 値を書き込む際、HTTP パラメータのバインドと Bulk Copy には重要な違いがあります。 Bulk Copy は対象カラムのタイムゾーンを認識しており、そのタイムゾーンで Unspecified の値を正しく解釈します。 HTTP Parameters はカラムのタイムゾーンを自動的には認識しません。SQL の型ヒントでそのタイムゾーンを指定する必要があります。

Decimal 型


JSON 型

JSON の書き込み時の動作は、JsonWriteMode 設定で制御されます。
  • String (デフォルト): stringJsonObjectJsonNode、または任意のオブジェクトを受け付けます。すべての入力は System.Text.Json.JsonSerializer でシリアライズされ、サーバー側でパースするために JSON 文字列として送信されます。これは最も柔軟なモードで、型登録なしで動作します。
  • Binary: 登録済みの POCO 型のみを受け付けます。データはクライアント側で、完全な型ヒントのサポート付きで ClickHouse のバイナリ JSON フォーマットに変換されます。使用する前に connection.RegisterJsonSerializationType<T>() を呼び出す必要があります。このモードで string または JsonNode の値を書き込むと、ArgumentException がスローされます。
型付き JSON カラム
JSON カラムに型ヒント (例: JSON(id UInt64, price Decimal128(2))) がある場合、ドライバーはそれらのヒントを使って、値を型情報を完全に保ったままシリアライズします。これにより、UInt64DecimalUUIDDateTime64 など、汎用的な JSON としてシリアライズすると精度が失われる可能性のある型でも、精度を保持できます。
POCO のシリアライゼーション
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 と定義されたヒントにのみ一致します。これは、userNameUserName のようなパスを別個のフィールドとして共存させられる 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 のみです) 。

その他の型


ジオメトリ型


書き込みではサポートされていません


ネスト型の扱い

ClickHouse のネスト型 (Nested(...)) は、配列として読み書きできます。

ログと診断

ClickHouse の .NET クライアントは、Microsoft.Extensions.Logging の抽象化レイヤーと統合されており、軽量で必要に応じて有効化できるログ機能を提供します。有効にすると、ドライバーは接続ライフサイクル イベント、コマンド実行、トランスポート処理、バルク挿入操作に関する構造化メッセージを出力します。ログ機能は完全に任意であり、ロガーを設定していないアプリケーションも追加のオーバーヘッドなしでそのまま動作し続けます。

クイックスタート

appsettings.json を使用する

.NET の標準構成機能を使用してログレベルを設定できます。

インメモリ構成を使用する

コード内で、カテゴリ別にログ出力の詳細度を設定することもできます。

カテゴリと出力元

ドライバーは専用のカテゴリを使用しているため、コンポーネントごとにログレベルを細かく調整できます。

例: 接続の問題を診断する

以下の内容がログに記録されます。
  • HTTP クライアント ファクトリの選択 (既定のプールまたは単一接続)
  • HTTP ハンドラーの設定 (SocketsHttpHandler または HttpClientHandler)
  • 接続プールの設定 (MaxConnectionsPerServer、PooledConnectionLifetime など)
  • タイムアウトの設定 (ConnectTimeout、Expect100ContinueTimeout など)
  • SSL/TLS の設定
  • 接続のオープン/クローズ イベント
  • セッション ID の追跡

デバッグモード: ネットワークトレースと診断

ネットワーク関連の問題の診断に役立てるため、ドライバーライブラリには .NET のネットワーク内部処理の低レベルトレースを有効にするヘルパーが含まれています。これを有効にするには、レベルを Trace に設定した LoggerFactory を渡し、EnableDebugMode を true に設定する必要があります (または ClickHouse.Driver.Diagnostic.TraceHelper クラスを使って手動で有効にします) 。イベントは ClickHouse.Driver.NetTrace カテゴリにログ出力されます。警告: これにより非常に大量の logs が生成され、パフォーマンスに影響します。本番環境でデバッグモードを有効にすることは推奨されません。

OpenTelemetry

このドライバーは、.NET System.Diagnostics.Activity API を通じて、OpenTelemetry の分散トレーシングをネイティブにサポートしています。有効にすると、ドライバーはデータベース操作に対するスパンを出力し、それらを Jaeger や ClickHouse 自体 (OpenTelemetry Collector 経由) などのオブザーバビリティバックエンドにエクスポートできます。

トレーシングを有効にする

ASP.NET Core アプリケーションでは、ClickHouse ドライバーの ActivitySource を OpenTelemetry の設定に追加します。
コンソールアプリケーション、テスト、または手動セットアップの場合:

スパン属性

各スパンには、標準的なOpenTelemetryのデータベース属性に加え、デバッグに利用できるClickHouse固有のクエリ統計情報が含まれます。

設定オプション

ClickHouseDiagnosticsOptions を使用して、トレーシングの動作を制御します。
IncludeSqlInActivityTags を有効にすると、トレースに機密データが含まれる可能性があります。本番環境での使用には注意してください。

TLS 設定

HTTPS 経由で ClickHouse に接続する場合、TLS/SSL の挙動はいくつかの方法で設定できます。

カスタム証明書の検証

本番環境でカスタムの証明書検証ロジックが必要な場合は、ServerCertificateCustomValidationCallback ハンドラーを構成した独自の HttpClient を指定します。
カスタム HttpClient を指定する際の注意事項
  • 自動圧縮解除: 圧縮が無効になっていない場合は、AutomaticDecompression を有効にする必要があります (圧縮はデフォルトで有効です) 。
  • アイドルタイムアウト: ハーフオープン接続による接続エラーを避けるため、PooledConnectionIdleTimeout はサーバーの keep_alive_timeout (ClickHouse Cloud では 10 秒) より短く設定してください。

ORM サポート

ORM では ADO.NET API (ClickHouseConnection) が必要です。接続のライフサイクルを適切に管理するため、ClickHouseDataSource から接続を作成してください。

Dapper

ClickHouse.Driver は Dapper に対応しています。ドライバーは、Dapper の @parameter 構文を ClickHouse のネイティブな {parameter:Type} 構文に自動変換し、型は .NET の値から推論されます。 適切に connection のライフタイムを管理するには、ClickHouseDataSource を使用します。

パラメーターの受け渡し形式

標準的な Dapper のパラメーター指定方法をすべてサポートしています。 匿名オブジェクト:
POCO クラス:
Dictionary:
DynamicParameters (ディクショナリまたは匿名オブジェクトから) :

POCO へのクエリ

Dapper は、カラム名に基づいてプロパティにマッピングします (大文字と小文字を区別しません) 。

ClickHouseネイティブのパラメーター構文

型を明示的に制御する必要がある場合は、パラメーター値に Dictionary<string, object> を使用し、SQL 内で ClickHouse の {param:Type} 構文を直接使用してください。同じパラメーターに対して @param 構文と {param:Type} 構文を併用しないでください。

WHERE IN

DapperのネイティブなIN展開が機能します:
Dapper はこれを WHERE id IN (@Ids1, @Ids2, @Ids3) に書き換え、ドライバーが展開された各パラメーターをそれぞれ変換します。 Array パラメーターを使った ClickHouse の has() も動作します:

カスタム型ハンドラー

ITupleBigIntegerClickHouseDecimal など、一部の ClickHouse の型では、起動時にハンドラーを登録する必要があります。
型ハンドラーの実装例は、Dapper の例を参照してください。

Dapper.Contrib

GetAll<T>()Get<T>(id) は動作します。Insert<T>() は動作しません。これは SQL Server の構文 (SCOPE_IDENTITY[]) を生成するためです。代わりに、ClickHouseClient のネイティブな InsertBinaryAsync メソッドを使用することを推奨します。
プロパティ名は ClickHouse のカラム名と完全に一致している必要があります (大文字と小文字を区別します) 。

制限事項

Linq2db

このドライバーは、.NET 向けの軽量な ORM/LINQ プロバイダーである linq2db に対応しています。詳細なドキュメントについては、プロジェクトの Web サイトを参照してください。 使用例: ClickHouse プロバイダーを使用して DataConnection を作成します。
テーブルのマッピングは、属性または Fluent API を使用して定義できます。クラス名とプロパティ名がテーブル名およびカラム名と完全に一致している場合は、設定は不要です。
クエリの実行:
バルクコピー: 効率的な一括挿入には BulkCopyAsync を使用します。

Entity Framework Core

ClickHouse 向けの公式 Entity Framework Core プロバイダーです。C# クラスを ClickHouse テーブルにマッピングし、LINQ でクエリを実行し、SaveChanges を通じてデータを insert できます。いずれも使い慣れた EF Core のパターンで行えます。
このプロバイダーは現在も活発に開発が進められています。現行の release では、LINQ クエリ (JOIN、subqueries、set operations を含む) 、SaveChanges / BulkInsertAsync による INSERT、完全な DDL (CREATE / ALTER / DROP) を伴う移行、そして ClickHouse 固有の table engine 設定をサポートしています。UPDATE / DELETE には対応していません。

インストール

.NET 10.0 と EF Core 10 が必要です。

クイックスタート

エンティティと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 を伴う GroupByHAVING (.GroupBy() の後に .Where() を使用) 、1 つのプロジェクション内での複数の集計、集計結果に対する OrderBy を含みます。 JOIN: Join (INNER) 、GroupJoin/SelectMany パターン (LEFT および CROSS) 。LEFT JOIN は、一致しない行に対して実際の null 値を返します (下記の LEFT JOIN の NULL セマンティクス を参照) 。 サブクエリ: 相関 Contains / INAny / EXISTSAll、およびプロジェクション内のスカラー サブクエリ。 集合演算: Concat (→ UNION ALL) 、Union (→ UNION DISTINCT) 、IntersectExcept インラインのローカルコレクション: インメモリコレクション (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 セマンティクス
このプロバイダーは、JOIN の挙動に関する Entity Framework の想定に合わせるため、接続のたびに set_join_use_nulls=1 を自動的に設定します。 ClickHouse サーバーまたは profile でこの設定の変更が禁止されている場合 (例: readonly=1 の profile) 、次のように無効化してください。
オプトアウトが有効な場合、LEFT JOIN は ClickHouse のカラムのデフォルト値を返すため、EF の null ベースのナビゲーション検出は期待どおりに機能しなくなります。== null の代わりに、0 / "" との明示的な比較を使用してください。

データの挿入

SaveChanges では、ドライバーが提供するネイティブの InsertBinaryAsync API を使用します。RowBinary エンコーディングと GZip 圧縮を利用するため、パラメーター化 SQL よりもはるかに効率的です。
エンティティは、保存後に他の EF Core プロバイダーと同様、Added から Unchanged に変わります。 バッチサイズ は設定できます (デフォルトは 1000) :

一括挿入

高スループットの読み込みでは、SaveChanges ではなく BulkInsertAsync を使用してください。これは DbContext の拡張メソッドで、EF Core の変更トラッカー、ID 解決、状態管理を完全にバイパスし、RowBinary エンコーディングと GZip 圧縮を使用して、ドライバーの InsertBinaryAsync を直接呼び出します。 そのため、挿入後にエンティティの追跡が不要な大規模データセットの読み込みに適しています。
入力には任意の IEnumerable<T> を使用できます。エンティティはすべてをメモリに読み込むことなく順次処理されます。戻り値は挿入された行数です。挿入後もエンティティは DbContext にアタッチされないため、AddedUnchanged の状態遷移は発生しません。

列挙型

ClickHouse Enum8/Enum16 カラムは、string プロパティまたは C# の enum 型にマッピングできます。C# の列挙型を使用する場合、プロバイダーは列挙型とその文字列表現の間で自動的に変換します。

カスタム型の変換

EF Core の ValueConverter システムを使うと、カスタム型をプロバイダーがすでにサポートしている型にマッピングできます。プロバイダーがカスタム型を直接扱うことはなく、EF Core がその境界で変換を行います。 プロパティ単位の変換:
再利用可能なコンバータークラス:

カラム型のアノテーション

stringintDateTime などのスカラー型では、プロバイダーが ClickHouse の型を自動的に推論します。パラメーター化された型やラッパーについては、ClickHouse の型を明示的に指定する必要があります。 データ アノテーション (属性) を使用する場合:
OnModelCreating で fluent API を使用する方法:
Array(Nullable(Int32))LowCardinality(Nullable(String)) のようなネストされたラッパー型をサポートしています — プロバイダーは NullableLowCardinality をどのネストレベルでも自動的にアンラップします。

Variant と Dynamic カラム

ClickHouse の Variant(T1, T2, ...) カラムおよび Dynamic カラムは、.NET では object にマップされます。object は自動的な型推論には汎用的すぎるため、.HasColumnType() でストア型を明示的に指定する必要があります。
読み取り時には、値は保存されている判別子に対応する .NET 型 (例: stringulongulong[]) に自動的にデシリアライズされます。

JSON カラム

このプロバイダーは ClickHouse の Json カラム型をサポートしており、System.Text.Json.Nodes.JsonNode (プライマリ) または string (自動 ValueConverter 使用時) に対応付けられます。
JSON の読み書きは、SaveChangesBulkInsertAsync の両方で利用できます:
生の JSON 文字列を使いたい場合は、プロパティを 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(...) で指定します:
標準の (スキップしない) 索引は、ClickHouse に相当するものがないため、黙って無視されます。一意索引については、ClickHouse では一意性が保証されないため、例外がスローされます。

移行

標準的な EF Core の移行ワークフロー:
サポートされている操作:

移行の制限事項

移行以外にも、このプロバイダーはまだ以下をサポートしていません。
  • UPDATE / DELETE
  • トランザクション: BeginTransaction は no-op です。ClickHouse は ACID トランザクションをサポートしていません。
  • JSON パス クエリの変換: LINQ の entity.Data["key"] は、ClickHouse の data.key SQL 構文に変換されません。JSON 以外のカラムでフィルタリングし、JSON はメモリ上で確認してください。

制限事項

AggregateFunction カラム

AggregateFunction(...) 型のカラムは、直接クエリしたり、挿入したりすることはできません。 挿入するには:
取得するには:

最終更新日 2026年7月2日