IHP中如何实现Instructor与OfficeAssignment的一对零或一关系
IHP框架一对零或一关系实现方案
IHP原生支持一对零或一关系语义,你可以通过以下两种方案实现,无需强行适配EF Core的表结构设计:
方案1:基于唯一约束实现(推荐,符合IHP默认约定)
无需修改office_assignments表默认的UUID主键id,仅需要做两处调整:
- 给外键
instructor_id添加唯一约束,保证数据库层面不会出现同一讲师对应多条办公室记录,在迁移脚本中执行以下SQL:CREATE UNIQUE INDEX unique_office_assignment_instructor ON office_assignments (instructor_id); - 手动修改
Schema.hs中的关联声明,将Instructor模型默认生成的HasMany复数关联改为HasOne单数关联:
把默认生成的关联代码:
替换为:instance HasMany "officeAssignments" Instructor where type Many "officeAssignments" Instructor = [OfficeAssignment] foreignKey = #instructorIdinstance HasOne "officeAssignment" Instructor where type One "officeAssignment" Instructor = Maybe OfficeAssignment foreignKey = #instructorId foreignTable = "office_assignments"
调整完成后,你可以直接通过instructor |> get #officeAssignment获取Maybe OfficeAssignment类型的结果,完全匹配零或一的业务语义。
方案2:基于外键主键实现(兼容EF Core原有表结构)
如果你需要完全对齐EF Core的表结构(用instructor_id作为office_assignments的主键),可以通过手动指定模型主键解决编译报错问题:
- 迁移脚本创建表时直接指定
instructor_id为主键:CREATE TABLE office_assignments ( instructor_id UUID PRIMARY KEY REFERENCES instructors(id) ON DELETE CASCADE, location TEXT NOT NULL, -- 其他业务字段 ); - 在
Schema.hs中手动指定OfficeAssignment模型的主键字段,覆盖IHP默认的id主键约定:data OfficeAssignment = OfficeAssignment { instructorId :: !(Id Instructor), location :: !Text -- 其他业务字段 } deriving (Eq, Show) instance Model OfficeAssignment where tableName = "office_assignments" primaryKey = #instructorId - 后续Instructor侧的
HasOne关联声明和方案1完全一致即可正常使用。
表单开发适配
后续开发关联表单时,直接判断instructor |> get #officeAssignment的返回值是Just还是Nothing,即可区分更新现有办公室记录还是新建办公室记录,逻辑和普通一对一关联表单完全一致。
内容的提问来源于stack exchange,提问作者dharmatech
相关产品推荐
相关产品推荐

