Docker部署PostgreSQL+.NET应用时,解决'relation "Subjects"不存在'错误
解决"relation 'Subjects' does not exist"错误的方案
1. 修正实体模型的主键与命名错误
(1)给Subject类标记主键
Subject类的id字段未添加[Key]特性,EF Core无法识别其为主键,会导致迁移生成的表结构异常。修改Subject类:
public class Subject { [Key] // 添加主键标记 public string? id {get;set;} public string? Title {get; set; } public int? Credits {get; set; } public virtual List<SubjectStudent> SubjectStudents {get; set;} // 修正为SubjectStudent(与中间类名一致) [ForeignKey("Teacher")] public int? TeacherDni {get; set;} public virtual Teacher Teacher {get; set;} }
(2)修正Student类的导航属性类型
Student类中Subjects属性的类型是ICollection<SubjectStudents>,但你的中间实体类是SubjectStudent(单数),类型不匹配会导致EF映射错误:
public class Student { [Key] public int? Dni {get; set;} public string? FirstName { get; set; } public string? SurName { get; set; } public string? Email {get; set; } public string? Password {get; set;} public DateTime EnrollmentDate { get; set; } public ICollection<SubjectStudent> Subjects { get; set; } // 修正为SubjectStudent }
(3)修正SubjectStudent类的导航属性与外键配置
中间类的导航属性命名和外键配置存在问题,需明确外键关联:
[PrimaryKey(nameof(SubjectId), nameof(StudentDni))] public class SubjectStudent { public string? SubjectId {get;set;} [ForeignKey(nameof(SubjectId))] // 添加外键标记 public Subject Subject {get;set;} // 修正为单数Subject,与类名对应 public int? StudentDni {get;set;} [ForeignKey(nameof(StudentDni))] // 添加外键标记 public virtual Student Student { get; set; } // 修正为单数Student }
2. 重新生成并应用数据库迁移
(1)本地项目重新生成迁移
打开终端,执行以下命令:
# 生成新的迁移文件 dotnet ef migrations add FixEntityModels # 将迁移应用到数据库 dotnet ef database update
(2)Docker环境下自动执行迁移
若使用Docker部署,需在应用启动时自动执行迁移。在Program.cs中添加代码:
var app = builder.Build(); // 自动应用未执行的迁移 using (var scope = app.Services.CreateScope()) { var dbContext = scope.ServiceProvider.GetRequiredService<YourDbContext>(); dbContext.Database.Migrate(); } // 后续中间件配置...
3. 适配PostgreSQL表名大小写规则
PostgreSQL默认区分表名大小写,而EF Core默认生成复数形式的表名(如Subjects)。可通过配置统一表名为小写:
在DbContext的OnModelCreating方法中添加:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 所有表名转为小写 foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { entityType.SetTableName(entityType.GetTableName().ToLower()); } // 也可单独指定表名 modelBuilder.Entity<Subject>().ToTable("subjects"); modelBuilder.Entity<SubjectStudent>().ToTable("subject_students"); }
4. 验证数据库表是否存在
进入PostgreSQL容器,执行SQL查询确认表是否生成:
-- 列出public schema下的所有表 SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
若未找到subjects、subject_students等表,需检查迁移日志或容器内的数据库连接字符串是否正确。
内容的提问来源于stack exchange,提问作者Gr22
相关产品推荐
相关产品推荐

