Vapor 中的数据库播种和预加载
Database seeding and Eager Loading in Vapor
这是我执行数据库播种的代码:
func prepare(on database: Database) -> EventLoopFuture<Void> {
var citySaveResults: [EventLoopFuture<Void>] = []
return User.query(on: database).first().flatMap({ user -> EventLoopFuture<Void> in
guard let userId = user?.id else { return citySaveResults.flatten(on: database.eventLoop).transform(to: ()) }
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()),
]
for city in cities {
city.plans.append(contentsOf: createPlans(cityId: city.id, userId: userId))
citySaveResults.append(city.save(on: database))
}
return citySaveResults.flatten(on: database.eventLoop) .transform(to: ())
})
}
但是它在队列中崩溃了:
city.plans.append(contentsOf: createPlans(cityId: city.id, userId: userId))
Fatal error: Children relation not eager loaded, use $ prefix to access.
有人可以向我解释一下在这种情况下如何使用预加载功能来避免崩溃吗?
这是我的城市模型:
final class City: Model {
static let schema = "cities"
@ID(key: .id) var id: UUID?
@Field(key: "name") var name: String
@Field(key: "isActive") var isActive: Bool
@Children(for: \Plan.$city) var plans: [Plan]
...
}
预加载顾名思义就是加载。保存子项需要先保存父项,再单独保存子项。
func prepare(on database: Database) -> EventLoopFuture<Void> {
var citySaveResults: [EventLoopFuture<Void>] = []
return User.query(on: database).first().flatMap { user -> EventLoopFuture<Void> in
guard let userId = user?.id else { return citySaveResults.flatten(on: database.eventLoop).transform(to: ()) }
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()),
]
for city in cities {
let saveResult = city.save(on: database).flatMap {
let plans = createPlans(cityId: city.id, userId: userId)
return plans.save(on: database)
}
citySaveResults.append(saveResult)
}
return citySaveResults.flatten(on: database.eventLoop) .transform(to: ())
}
}
这是我执行数据库播种的代码:
func prepare(on database: Database) -> EventLoopFuture<Void> {
var citySaveResults: [EventLoopFuture<Void>] = []
return User.query(on: database).first().flatMap({ user -> EventLoopFuture<Void> in
guard let userId = user?.id else { return citySaveResults.flatten(on: database.eventLoop).transform(to: ()) }
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()),
]
for city in cities {
city.plans.append(contentsOf: createPlans(cityId: city.id, userId: userId))
citySaveResults.append(city.save(on: database))
}
return citySaveResults.flatten(on: database.eventLoop) .transform(to: ())
})
}
但是它在队列中崩溃了:
city.plans.append(contentsOf: createPlans(cityId: city.id, userId: userId))
Fatal error: Children relation not eager loaded, use $ prefix to access.
有人可以向我解释一下在这种情况下如何使用预加载功能来避免崩溃吗?
这是我的城市模型:
final class City: Model {
static let schema = "cities"
@ID(key: .id) var id: UUID?
@Field(key: "name") var name: String
@Field(key: "isActive") var isActive: Bool
@Children(for: \Plan.$city) var plans: [Plan]
...
}
预加载顾名思义就是加载。保存子项需要先保存父项,再单独保存子项。
func prepare(on database: Database) -> EventLoopFuture<Void> {
var citySaveResults: [EventLoopFuture<Void>] = []
return User.query(on: database).first().flatMap { user -> EventLoopFuture<Void> in
guard let userId = user?.id else { return citySaveResults.flatten(on: database.eventLoop).transform(to: ()) }
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()),
]
for city in cities {
let saveResult = city.save(on: database).flatMap {
let plans = createPlans(cityId: city.id, userId: userId)
return plans.save(on: database)
}
citySaveResults.append(saveResult)
}
return citySaveResults.flatten(on: database.eventLoop) .transform(to: ())
}
}