ClickHouse / ClickHouse/ClickHouse.EntityFrameworkCore
Migrations: split each migration into single-DDL steps (ClickHouse has no transactions)
- 主要言語
- C#
- スター
- 23
- フォーク
- 7
- 平均マージ
- 14日 3時間
- マージ済み PR(30日)
- 1
説明
**Background**
EF Core assumes a migration is atomic: the whole Up() runs inside a transaction, and the row in __EFMigrationsHistory is written only if every operation succeeds. If anything fails, the transaction rolls back and the database is left exactly as it was, so the migration can simply be re-run.
ClickHouse has no transactions for DDL. There is no multi-statement atomicity and no rollback. Each CREATE / ALTER / DROP commits the moment it executes.
The problem
A normal EF migration bundles many DDL operations into one Up():
```protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable("events", /* … */); // DDL_1
migrationBuilder.CreateTable("events_by_day", /* … */); // DDL_2
migrationBuilder.CreateClickHouseMaterializedView( // DDL_3 (depends on DDL_1 + DDL_2)
viewName: "events_mv", targetTable: "events_by_day",
selectQuery: "SELECT day, count() FROM events GROUP BY day");
}
```
EF runs these as a single migration and writes the history row only after DDL_3 succeeds. Now suppose DDL_3 fails (a bad SELECT, an unsupported engine, a transient server error). Because there is no transaction:
- DDL_1 and DDL_2 are already committed: events and events_by_day exist on the server.
- The migration is not recorded as applied (no history row).
The migration is now wedged. Re-running it re-executes DDL_1: CREATE TABLE events → Code: 57. Table already exists. It can never complete, and the database is stuck in a half-applied state that has to be cleaned up by hand.
This is not an edge case, any migration with more than one DDL statement is exposed to it, and the larger the migration the worse the partial-failure blast radius.
Proposed approach: one DDL statement per migration step
Instead of one migration containing N operations, split a single dotnet ef migrations add into N single-operation step migrations, each with its own __EFMigrationsHistory row:
```
20260601120000_Init_001 CREATE TABLE `events` …
20260601120000_Init_002 CREATE TABLE `events_by_day` …
20260601120000_Init_003 CREATE MATERIALIZED VIEW `events_mv` …
```
Now a partial failure is resumable:
- If _003 fails, _001 and _002 are each recorded as applied.
- Fix the model and re-run database update → it skips _001/_002 (already in history) and resumes at _003.
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
調査の方向性
The issue identifies migration Up(), MigrationBuilder, and __EFMigrationsHistory as the relevant entry points. Start by tracing how the provider executes multiple DDL operations and records migration history. Done means the proposed single-DDL steps preserve ordering and allow a later failed step to resume without re-executing completed steps.
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- csharp, sql
- 領域
- backend, databases
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 静か
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 35/100