最近在研究EF的CodeFirst模式下使用SQLite进行数据库的开发,需要简单的使用数据库的增删查改。因为不是专业的数据库专家,因此使用过程出现了很多问题。其中一个就是数据库迁移的问题。
网络上看到的代码示例,很多是基于SqlServer和MySql的,测试过程中发现很多函数多不能使用,造成了很多困惑。最后发现了SQLite的局限性。
SQLite 提供程序有一些迁移限制,其中大部分是底层 SQLite 数据库引擎的限制造成的,并不是 EF 特定的。
参考的链接:SQLite - SQLite 局限性 - 《微软 EntityFrameworkCore 中文文档》 - 书栈网 · BookStack
SQLite 数据库引擎不支持一些其他主要的关系数据库支持的模式操作。如果尝试将不被支持的操作应用到 SQLite 数据库,将会抛出 NotSupportedException 异常。
操作 | 支持状态 |
AddColumn(添加数据列) | ✔ |
AddForeignKey(添加外键) | ✗ |
AddPrimaryKey(添加主键) | ✗ |
AddUniqueConstraint(添加唯一约束) | ✗ |
AlterColumn(修改数据列) | ✗ |
CreateIndex(创建索引) | ✔ |
CreateTable(创建数据表) | ✔ |
DropColumn(删除数据列) | ✗ |
DropForeignKey(删除外键) | ✗ |
DropIndex(删除索引) | ✔ |
DropPrimaryKey(删除主键) | ✗ |
DropTable(删除数据表) | ✔ |
DropUniqueConstraint(删除唯一约束) | ✗ |
RenameColumn(重命名数据列) | ✗ |
RenameIndex(重命名索引) | ✗ |
RenameTable(重命名表名) | ✔ |
可以在迁移中手动编写代码来执行数据表重建,这样可以解决一些局限性问题。一个数据表的重建包括重命名已有的数据表、创建新表、复制数据到新表以及删除旧的数据表。这将需要使用 Sql(string) 方法来执行其中一些步骤。
参考示例:
public partial class UpdateBusTable : DbMigration{ public override void Up() { Sql(@"PRAGMA foreign_keys = 0; CREATE TABLE sqlitestudio_temp_table AS SELECT * FROM Bus; DROP TABLE Bus; CREATE TABLE Bus ( Id NVARCHAR (128) NOT NULL, Name NVARCHAR (2147483647), RunCount INT DEFAULT (0), CreateTime DATETIME NOT NULL, PRIMARY KEY (Id) ); INSERT INTO Bus ( Id, Name, RunCount ) SELECT Id, Name, RunCount FROM sqlitestudio_temp_table; DROP TABLE sqlitestudio_temp_table; PRAGMA foreign_keys = 1;"); } public override void Down() { DropColumn("dbo.Bus", "CreateTime"); }}
平时很少写sql语句,可能在手动写sql语句时出现问题,找到一个工具,可以在修改数据库表的时候,生成迁移语句,操作流程如下:
以添加一个字段为例,生成sql语句步骤如下:
public partial class UpdateBusTable : DbMigration{ public override void Up() { Sql(@"PRAGMA foreign_keys = 0; CREATE TABLE sqlitestudio_temp_table AS SELECT * FROM Bus; DROP TABLE Bus; CREATE TABLE Bus ( Id NVARCHAR (128) NOT NULL, Name NVARCHAR (2147483647), RunCount INT DEFAULT (0), CreateTime DATETIME NOT NULL, PRIMARY KEY (Id) ); INSERT INTO Bus ( Id, Name, RunCount ) SELECT Id, Name, RunCount FROM sqlitestudio_temp_table; DROP TABLE sqlitestudio_temp_table; PRAGMA foreign_keys = 1;"); } public override void Down() { DropColumn("dbo.Bus", "CreateTime"); }}