SQLite EF Core データベース プロバイダーの制限事項
SQLite プロバイダーには、移行に関していくつかの制限事項があります。 これらの制限事項の多くは、基になる SQLite データベース エンジンでの制限事項の結果であり、EF に固有のものではありません。
モデリングの制限事項
共通のリレーショナル ライブラリ (Entity Framework リレーショナル データベース プロバイダーによって共有されている) には、ほとんどのリレーショナル データベース エンジンに共通のモデリング概念用の API が定義されています。 これらの概念のいくつかは、SQLite プロバイダーによってサポートされていません。
- スキーマ
- シーケンス
- データベースで生成されたコンカレンシー トークン (ドキュメントを参照)
クエリの制限事項
SQLite では、次のデータ型はネイティブにサポートされていません。 EF Core ではこれらの型の値に関して読み取りと書き込みを行うことができます。また、等しいかどうかのクエリ (where e.Property == value
) もサポートされています。 ただし、比較や順序付けなどの他の操作では、クライアントでの評価が必要になります。
- DateTimeOffset
- 10 進数
- TimeSpan
- UInt64
DateTimeOffset
ではなく、DateTime 値を使用することをお勧めします。 複数のタイム ゾーンを処理する場合は、値を保存する前に UTC に変換してから、適切なタイム ゾーンに再び変換することをお勧めします。
Decimal
型では、高レベルの精度が提供されます。 ただし、そのレベルの精度が不要な場合は、代わりに double を使用することをお勧めします。 クラスで decimal の使用を継続するには、値コンバーターを使用できます。
modelBuilder.Entity<MyEntity>()
.Property(e => e.DecimalProperty)
.HasConversion<double>();
移行に関する制限事項
SQLite データベース エンジンでは、他の大多数のリレーショナル データベースでサポートされているいくつかのスキーマ操作がサポートされていません。 サポートされていない操作のいずれかを SQLite データベースに適用しようとすると、NotSupportedException
がスローされます。
特定の操作を実行するためにはリビルドが試行されます。 リビルドが可能なのは、EF Core モデルの一部であるデータベース成果物に対してのみです。 データベース成果物がそのモデルの一部ではない (たとえば、移行内に手動で作成された) 場合も、NotSupportedException
がスローされます。
操作 | サポート対象? |
---|---|
AddCheckConstraint | ✔ (リビルド) |
AddColumn | ✔ |
AddForeignKey | ✔ (リビルド) |
AddPrimaryKey | ✔ (リビルド) |
AddUniqueConstraint | ✔ (リビルド) |
AlterColumn | ✔ (リビルド) |
CreateIndex | ✔ |
CreateTable | ✔ |
DropCheckConstraint | ✔ (リビルド) |
DropColumn | ✔ (リビルド) |
DropForeignKey | ✔ (リビルド) |
DropIndex | ✔ |
DropPrimaryKey | ✔ (リビルド) |
DropTable | ✔ |
DropUniqueConstraint | ✔ (リビルド) |
RenameColumn | ✔ |
RenameIndex | ✔ (リビルド) |
RenameTable | ✔ |
EnsureSchema | ✔ (no-op) |
DropSchema | ✔ (no-op) |
Insert | ✔ |
更新 | ✔ |
削除 | ✔ |
移行に関する制限事項の回避策
リビルドを実行するために移行でコードを手動で記述することによって、これらの制限事項の一部を回避できます。 テーブルのリビルドには、新しいテーブルの作成、新しいテーブルへのデータのコピー、古いテーブルの削除、新しいテーブルの名前変更が必要です。 これらの手順の一部を実行するには、Sql(string)
メソッドを使用する必要があります。
詳細については、SQLite のドキュメントで、他の種類のテーブル スキーマ変更を行う方法に関する記事を参照してください。
べき等スクリプトの制限事項
他のデータベースとは異なり、SQLite には手続き型の言語が含まれていません。 このため、べき等移行スクリプトに必要な if then ロジックを生成する方法はありません。
データベースに適用された最後の移行がわかっている場合は、その移行から最新の移行にスクリプトを生成できます。
dotnet ef migrations script CurrentMigration
それ以外の場合は、dotnet ef database update
を使用して移行を適用することをお勧めします。 このコマンドを実行するときにデータベース ファイルを指定できます。
dotnet ef database update --connection "Data Source=My.db"
同時移行の保護
EF9 では、移行の実行時にロック メカニズムが導入されました。 これは、データベースが破損状態になる可能性があるため、同時に発生する複数の移行実行から保護することを目的としています。 これは、 DbContext.Database.Migrate()
メソッドを使用して実行時に移行を適用することによって生じる潜在的な問題の 1 つです (詳細については、 移行の適用 を参照してください)。 これを軽減するために、EF は移行操作が適用される前に、データベースに排他ロックを作成します。
残念ながら、SQLite には組み込みのロック メカニズムがないため、EF は別のテーブル (__EFMigrationsLock
) を作成し、ロックに使用します。 移行が完了し、シード処理コードの実行が完了すると、ロックが解放されます。 ただし、何らかの理由で復旧不可能な方法で移行が失敗した場合、ロックが正しく解放されない可能性があります。 この場合、連続する移行は SQL の実行をブロックされるため、完了しません。 データベース内の __EFMigrationsLock
テーブルを削除することで、手動でブロックを解除できます。
関連項目
.NET