问题说明
最近在研究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语句时出现问题,找到一个工具,可以在修改数据库表的时候,生成迁移语句,操作流程如下:
- 下载sqlite工具:SALiteStudio
- 生成数据库迁移sql语句
以添加一个字段为例,生成sql语句步骤如下:
- 步骤一:打开数据库,找到要修改的表,在“结构”页面,选择“Add Column”
- 步骤二:填写字段信息,点击OK
- 步骤三:点击Commit structure changes,自动弹出将要执行的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");
}
}
本文暂时没有评论,来添加一个吧(●'◡'●)