使用EF Core更新与修改生产数据库( 二 )


由于我使用了Identity,在数据中有对应的AspNet开头的表,这些表我并不在本系统中使用(其他系统需要用),因此我删除了对应的模型、snapshot、DbContext记录,运行Add-Migration,生成了如下文件:
protected override void Up(MigrationBuilder migrationBuilder){migrationBuilder.DropTable(name: "AspNetRoleClaim");migrationBuilder.DropTable(name: "AspNetUserClaim");migrationBuilder.DropTable(name: "AspNetUserLogin");migrationBuilder.DropTable(name: "AspNetUserRoles");migrationBuilder.DropTable(name: "AspNetUserToken");migrationBuilder.DropTable(name: "AspNetRole");migrationBuilder.DropTable(name: "AspNetUser");}说明现在已经能够正常跟踪我们的修改了,不过我这里需要保留对应的表,因此删除up与down的所有内容 。
注意以下几点:
更新模型名称如果使用fluentAPI,那么模型对应的表名称会直接在fluentAPI中直接指定,只修改模型的名称没有任何效果 。修改的话,可以修改对应的fluentAPI,或者换用Annotation
提示找不到constraint对于修改主键、索引等内容的情况,如果不是通过EF Core建立的数据库,那么命名规则可能不一样 。对于postgresql数据库,可以用这个查询名称,然后修改对应的migration文件内容即可 。
SELECT * FROM pg_CONSTRAINT复合主键的限制对于使用两列或者以上列作为复合主键的情况,使用EnsureCreated方法是可以识别Annotation形式的主键的 。
[Key][Column(Order = 1)]public string DeviceId { get; set; }[Key][Column(Order = 2)]public long Timestamp { get; set; }使用Migration的时候,这种形式无法识别,需要在OnModelCreating()中,使用fluentAPI
modelBuilder.Entity<DeviceData>().HasKey(w => new { w.DeviceId, w.Timestamp });Command执行超时默认Command执行的超时设置只有30s,对一些大一点的表来说,是不太够的 。可以设置:
optionsBuilder.UseNpgsql("Server=xxxxxxxxxxxxx", opt=>opt.CommandTimeout(3000));增加命令执行的超时时间 。
多个连接字符串的情况如果程序使用了appsettings.Development.json之类的文件存储连接字符串,那么需要指定环境是Production(生产数据库),否则可能还原到本地数据库去了 。对于nuget包管理控制台(使用update-database),执行:
$Env:ASPNETCORE_ENVIRONMENT = "Development"Update-Database对于使用dotnet ef工具集的,直接执行:
dotnet ef database update --environment Developmentcannot be cast automatically to type设计数据库表如果修改列的数据类型(比如从varchar到integer),Postgresql会提示这个问题,导致无法修改 。可以在migrationbuilder中使用sql,按照提示添加"USING "x"::integer"解决 。但是这种方法还是不太优雅,手动处理Up()之后,还需要处理Down(),否则将无法正确还原 。
可以使用分步的方法进行,假设我们需要将Id从varchar改成int4

  1. 添加一个字段temp,类型为int4,设置为[Key],然后删除Id字段 。
  2. 添加并应用迁移
  3. 修改temp名称为Id
  4. 添加并应用迁移
多次应用迁移每次修改尽量少一点,然后update-database,这样更容易发现问题,对于有
使用EF Core更新与修改生产数据库

文章插图
这种提示的,一定要检查生成语句中Drop相关的语句 。
本地数据库与生产数据库,都有__EFMigrationsHistory记录相关的迁移情况 。在生产与本地数据库中进行切换是,不用担心顺序问题,Update-Database会一个个应用迁移直到最新 。

经验总结扩展阅读