SQLite EF Core 資料庫提供者限制
SQLite 提供者有許多移轉限制。 這些限制大部分都是基礎 SQLite 資料庫引擎的限制的結果,而且不是 EF 特有的。
模型限制
通用關係庫(由 EF Core 關係資料庫提供者共用)會定義 API,以模型化大部分關係資料庫引擎通用的概念。 SQLite 提供者不支援其中幾個概念。
- 結構描述
- 序列
- 資料庫產生的並行令牌(請參閱檔案)
查詢限制
SQLite 原生不支援下列數據類型。 EF Core 可以讀取和寫入這些類型的值,也支援查詢相等 (where e.Property == value
) 。 不過,其他作業,例如比較和排序,將需要客戶端的評估。
DateTimeOffset
decimal
TimeSpan
ulong
我們建議使用 DateTime
值,而不是 DateTimeOffset
。 處理多個時區時,建議您先將值轉換成 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 | ✔ (不操作) |
DropSchema | ✔ (不操作) |
插入 | ✔ |
更新 | ✔ |
刪除 | ✔ |
移轉限制因應措施
您可以在移轉中手動撰寫程式代碼來執行重建,以因應這些限制的一些。 數據表重建涉及建立新的數據表、將數據複製到新數據表、卸除舊數據表、重新命名新數據表。 您必須使用 Sql 方法來執行其中一些步驟。
如需詳細資訊,請參閱 SQLite 檔中的其他資料表架構變更 。
等冪腳本限制
與其他資料庫不同,SQLite 不包含程序語言。 因此,無法產生等冪移轉腳本所需的 if-then 邏輯。
如果您知道最後套用至資料庫的移轉,您可以從該移轉產生腳本到最新的移轉。
dotnet ef migrations script CurrentMigration
否則,建議您使用 dotnet ef database update
來套用移轉。 您可以在執行 命令時指定資料庫檔案。
dotnet ef database update --connection "Data Source=My.db"
並行移轉保護
EF9 在執行移轉時引進了鎖定機制。 其旨在防止同時執行多個移轉,因為這可能會使資料庫處於損毀狀態。 這是使用 方法在運行時間套用 Migrate 移轉所造成的其中一個潛在問題(如需詳細資訊,請參閱 套用移轉 )。 為了減輕這種情況,EF 會在套用任何移轉作業之前,先在資料庫上建立獨佔鎖定。
不幸的是,SQLite 沒有內建鎖定機制,因此 EF Core 會建立個別的數據表(__EFMigrationsLock
),並將其用於鎖定。 移轉完成且植入程式代碼完成執行時,即會釋放鎖定。 不過,如果基於某些原因,移轉會以無法復原的方式失敗,可能無法正確釋放鎖定。 如果發生這種情況,連續移轉將會遭到封鎖而無法執行 SQL,因此永遠不會完成。 您可以藉由刪除資料庫中的 __EFMigrationsLock
資料表,手動解除封鎖它們。