/ 技术

Entity Framework Core SQLite provider向已存在的表中添加外键

SQLite本身不支持向已创建的表中添加外键,类似的限制还有很多,比较蛋疼,具体可以参见SQLite Limitations

项目中,如果是测试的时候,数据不是很重要的话,最方便的方法就是把已经创建的Migrations包括ModelSnapshot都删掉,重新Add-Migration重建数据库。

对于已经发布的应用,数据库不能删了创建的话,可以“曲线救国”。

假设需要给TableA添加一个需要建立外键的字段ColumnA,为了增加难度,假设TableB中的Column

B是TableA的外键。具体操作方法如下:

  1. 先在代码中TableA里添加ColumnA(不设置外键),Add-Migration,更新到线上数据库
  2. 将本地的数据库改名为database-backup,删除项目中所有Migrations和ModelSnapshot,创建一个RebuildDatabase的Migration,创建全新的数据库,从新数据库中复制TableA的Create Statement SQL语句并将改SQL语句中的表名改为TableA-New
  3. 在线上数据库中执行步骤2中的SQL语句,将创建TableA-New(已经含有外键约束了)
  4. 导出线上数据库中TableA中的数据到SQL文件中,并将该SQL文件中的表名改为TableA-New
  5. 将步骤4中的SQL文件的数据导入到线上数据库中
  6. 将线上数据库的TableA改名为TableA-Old,将TableA-New改名为TableA
  7. 因为重命名的关系,这时候TableB中的ColumnB是TableA-Old的外键,通过如下方法,将TableB中的外键约束改到TableA中:复制TableB的Create Statement,创建一个TableB-New,其中的ColumnB是TableA的外键,然后将TableB改名为TableB-Old,并将TableB-New改名为TableB(如果还有TableC中有TableB-Old的外键,通过同样的方法操作,以此类推),删除TableB-Old。(如果没有这样的TableB,则此步骤省略)
  8. 删除TableAOld
  9. 清空线上数据库__EFMigrationHistory表中的数据,并手动添加一条数据,以RebuildDatabase的Migration的文件名作为MigrationId,并输入当前的ProductVersion

收工!