EF Core生成的PostgreSQL迁移SQL语法错误,是否为版本兼容问题?
解答:PostgreSQL 9.6中
GENERATED语法错误问题 1. GENERATED BY DEFAULT AS IDENTITY的含义
这个语法是PostgreSQL用于定义自增主键列的标准SQL实现,从PostgreSQL 10开始正式引入,用来替代之前常用的SERIAL伪类型。它的核心作用是让数据库自动为该列生成递增数值,同时提供了比SERIAL更灵活的控制能力(比如可以设置GENERATED ALWAYS AS IDENTITY来禁止手动插入值)。
但你的PostgreSQL版本是9.6.15,这个版本完全不支持GENERATED相关语法,所以执行迁移生成的SQL时才会触发42601: syntax error at or near "GENERATED"的错误。
2. 是否需要升级PostgreSQL版本?
分两种情况权衡:
- 优先推荐升级:如果你的环境允许升级,强烈建议升级到PostgreSQL 10及以上版本。一方面
IDENTITY是标准SQL的特性,比SERIAL更规范、功能更完善;另一方面你使用的Npgsql.EntityFrameworkCore.PostgreSQL3.0.0版本本身就只支持PostgreSQL 10+,升级后能更好地兼容后续EF Core的特性迭代。 - 无法升级时的替代方案:如果暂时不能升级数据库,就需要调整EF Core的配置,让它生成PostgreSQL 9.6支持的
SERIAL语法。
3. 无法升级数据库时的具体解决方案
方案一:修改现有迁移代码
直接修改你已生成的迁移类,把自增列的注解从IdentityByDefaultColumn改成SerialColumn:
protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( name: "WeatherForecasts", columns: table => new { Id = table.Column<int>(nullable: false) // 替换自增策略注解 .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), Date = table.Column<DateTime>(nullable: false), TemperatureC = table.Column<int>(nullable: false), Summary = table.Column<string>(nullable: true) }, constraints: table => { table.PrimaryKey("PK_WeatherForecasts", x => x.Id); }); }
修改后重新执行Update-Database命令即可正常应用迁移。
方案二:全局配置默认自增策略
为了避免后续生成的迁移再出现同样问题,可以在你的DbContext中全局配置使用SERIAL列:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql("你的数据库连接字符串", builder => builder.UseSerialColumns()); }
额外注意:NuGet包版本兼容性
你当前使用的Npgsql.EntityFrameworkCore.PostgreSQL 3.0.0和.NET Core 2.2并不完全匹配,而且3.x版本默认针对PostgreSQL 10+优化。如果坚持用PostgreSQL 9.6,建议把Npgsql相关包降级到2.2.x版本(和你的.NET Core版本一致),这样默认就会生成SERIAL语法,不需要额外配置。
内容的提问来源于stack exchange,提问作者Aeptitude
相关产品推荐
相关产品推荐

