通过


SQLite EF Core 数据库提供程序限制条件

SQLite 提供程序存在大量迁移限制。 其中大多数限制源自底层 SQLite 数据库引擎中存在的限制,并不特定于 EF。

建模限制

常见的关系库(由 EF Core 关系数据库提供程序共享)定义了用于建模概念的 API,这些概念是大多数关系数据库引擎通用的。 SQLite 提供程序不支持其中的数个概念。

  • 模式
  • 序列
  • 数据库生成的并发令牌(请参阅文档

查询限制

SQLite 本身不支持以下数据类型。 EF Core 可以读取和写入这些类型的值,并且还支持查询相等性 (where e.Property == value)。 但对比和排序等其他操作需要对客户端进行评估。

  • DateTimeOffset
  • decimal
  • TimeSpan
  • ulong

建议使用 DateTimeOffset 值,而不是 DateTime。 处理多个时区时,建议将值转换为 UTC 再保存,然后转换回适当的时区。

decimal 类型的准确度高。 但是,如果不需要该级别的精度,我们建议改用 double。 可以使用值转换器继续在类中使用 decimal

modelBuilder.Entity<MyEntity>()
    .Property(e => e.DecimalProperty)
    .HasConversion<double>();

迁移限制

SQLite 数据库引擎不支持大多数其他关系数据库所支持的许多架构操作。 如果尝试在 SQLite 数据库进行某一种不受支持的操作,则会引发 NotSupportedException

将尝试进行重建以执行某些操作。 仅可重新构建属于 EF Core 模型的数据库组件。 如果数据库项目不是模型的一部分(例如,如果在迁移中手动创建数据库项目)则仍会引发 NotSupportedException

操作 是否支持?
添加检查约束 ✔(重新构建)
添加列
AddForeignKey ✔(重新构建)
添加主键 ✔(重新构建)
AddUniqueConstraint ✔(重新构建)
AlterColumn ✔(重新构建)
CreateIndex
创建表
删除检查约束 ✔(重新构建)
删除列 ✔(重新构建)
DropForeignKey ✔(重新构建)
DropIndex
删除主键 ✔(重新构建)
DropTable
删除唯一约束 ✔(重新构建)
重命名列
重命名索引 ✔(重新构建)
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 引入了一种 迁移锁定机制 ,以防止并发迁移执行。 与使用会话级应用程序锁(sp_getapplock)在连接关闭时自动释放的SQL Server不同,SQLite 没有内置的应用程序锁。 EF Core 改为创建一个 __EFMigrationsLock 表,并插入一行来获取锁。

处理已放弃的锁

如果应用程序意外终止(例如,在迁移期间进程已终止),则表中的锁行 __EFMigrationsLock 可能无法清除。 这会阻止任何后续迁移完成,因为每次尝试都会无限期地等待锁定释放。

若要清除放弃的锁,请从数据库中删除__EFMigrationsLock表:

DROP TABLE "__EFMigrationsLock";

或者,删除表中的所有行:

DELETE FROM "__EFMigrationsLock";

清除锁后,后续迁移操作将正常进行。 该表会根据需要自动重新创建。

另请参阅