You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vapor中Database Seeding操作Children关系未Eager Loading崩溃如何解决

Vapor Database Seeding 关联属性崩溃解决方案

错误原因

你遇到的崩溃和Eager Loading没有直接关系,Eager Loading是查询数据时用来优化性能、避免N+1查询的特性,本次崩溃的核心是@Children属性的设计限制:
@Children是Vapor Fluent专为读取关联数据设计的属性包装器,只读不可直接修改,直接访问不带$前缀的plans属性时,如果没有提前从数据库加载过关联数据,就会触发你看到的崩溃提示。

正确实现方案

1. 填充数据场景的写法(不需要Eager Loading)

新增关联数据时不需要修改City的plans属性,只需要给子模型Plan的关联父属性赋值后保存即可自动建立关联,修改后的填充代码如下:

func prepare(on database: Database) -> EventLoopFuture<Void> {
    return User.query(on: database).first().flatMap { user -> EventLoopFuture<Void> in
        guard let userId = user?.id else {
            return database.eventLoop.makeSucceededVoidFuture()
        }
        let cities = [
            City(id: UUID(), name: "London", isActive: true, createdAt: Date()),
            City(id: UUID(), name: "New York", isActive: true, createdAt: Date()),
            City(id: UUID(), name: "San Francisco", isActive: true, createdAt: Date()),
        ]
        let operationFutures = cities.map { city in
            // 先保存City,确保ID持久化到数据库
            return city.save(on: database).flatMap { _ in
                // 生成关联的Plan数组,createPlans内部已经为每个Plan的cityId赋值
                let plans = createPlans(cityId: city.id, userId: userId)
                // 批量保存所有Plan,自动建立和City的关联
                return plans.create(on: database)
            }
        }
        return operationFutures.flatten(on: database.eventLoop)
    }
}

2. 查询场景的Eager Loading正确用法

如果你在查询数据时需要访问City的plans属性,只需要在查询时添加with方法启用Eager Loading即可,示例代码如下:

City.query(on: database)
    .with(\.$plans) // 此处加$前缀访问关系键路径,启用Eager Loading
    .all()
    .whenSuccess { cities in
        // 此时plans数据已经提前加载完成,直接访问不会崩溃
        for city in cities {
            print("\(city.name) 关联计划数:\(city.plans.count)")
        }
    }

内容的提问来源于stack exchange,提问作者KrzysiekS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 23:09:03