EF Core+PostgreSQL遇System.InvalidCastException:modifiedbyuserid列为空
解决EF Core操作PostgreSQL时的System.InvalidCastException(列值null但模型已设为可空)
问题根源
这个错误的核心原因是EF Core与PostgreSQL的列名映射不匹配,导致EF错误地将已定义为可空的属性按非可空类型处理。具体来说:
- PostgreSQL默认会把未加双引号的列名转为小写存储(比如建表时的
ModifiedByUserID实际存储为modifiedbyuserid) - EF Core的Npgsql提供器默认遵循「C# PascalCase属性映射到PostgreSQL snake_case列」的规则,但你的模型属性命名(如
Modifiedbyuserid)不符合标准PascalCase,同时数据库列名也不是snake_case格式,最终导致映射错位,EF尝试用非可空的读取逻辑处理null值。
解决方案
方案1:显式配置实体与数据库列的映射
在DbContext的OnModelCreating方法中,手动指定每个属性对应的数据库列名,确保完全匹配:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>(entity => { entity.ToTable("Users"); entity.Property(e => e.Userid) .HasColumnName("UserID"); entity.Property(e => e.Username) .HasColumnName("Username"); entity.Property(e => e.Firstname) .HasColumnName("FirstName"); entity.Property(e => e.Lastname) .HasColumnName("LastName"); entity.Property(e => e.Createdate) .HasColumnName("CreateDate"); entity.Property(e => e.Modifieddate) .HasColumnName("ModifiedDate"); entity.Property(e => e.Disabled) .HasColumnName("Disabled"); entity.Property(e => e.Createdbyuserid) .HasColumnName("CreatedByUserID"); entity.Property(e => e.Modifiedbyuserid) .HasColumnName("ModifiedByUserID"); }); }
方案2:修正模型命名规范并匹配数据库最佳实践
把模型属性改成符合C#规范的PascalCase,同时将数据库列名调整为PostgreSQL推荐的snake_case格式,这样EF默认映射规则就能自动匹配:
修正后的C#模型:
public partial class User { public User() { } public long UserId { get; set; } public string Username { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime CreateDate { get; set; } public DateTime ModifiedDate { get; set; } public bool Disabled { get; set; } public long? CreatedByUserId { get; set; } public long? ModifiedByUserId { get; set; } }
调整后的数据库表结构(推荐):
CREATE TABLE Users ( user_id BIGSERIAL PRIMARY KEY, username VARCHAR(255) NOT NULL, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, create_date TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'), modified_date TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'), disabled BOOL NOT NULL DEFAULT False, created_by_user_id BIGINT, modified_by_user_id BIGINT );
方案3:统一EF Core与Npgsql包版本
你的项目中EF Core版本为6.0.8,但Npgsql相关包是6.0.6,版本不一致可能引发兼容性问题。将Npgsql和Npgsql.EntityFrameworkCore.PostgreSQL的版本升级到6.0.8,与EF Core版本保持一致:
<PackageReference Include="Npgsql" Version="6.0.8" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.8" />
验证步骤
- 应用上述任一方案后,清理并重新生成项目
- 若修改了表结构,执行数据库迁移
- 重新运行查询代码,确认错误消失
内容的提问来源于stack exchange,提问作者James Anderbard
相关产品推荐
相关产品推荐

