typeorm-seeding
typeorm-seeding copied to clipboard
Override params while seeding database
While I'm trying to seed a database with so many entities related, I found a problem and want to known if it is designed to work like this or if it is a bug.
Imagine that I have something like this:
define(EntityOne, (faker: typeof Faker) => {
const entity = new EntityOne()
const anotherField = factory(EntityTwo)() as any
entity.title = faker.random.word()
entity.anotherField = entityTwo
return entity
})
define(EntityTwo, (faker: typeof Faker) => {
const entity = new EntityTwo()
entity.uniqueNumber = faker.random.number(10)
return entity
})
and imagine that I have a UNIQUE flag on uniqueNumber on typeorm entity and generate only 10 possible values because it is something an iso-code.
If I try to run something like this:
const entityTwo = await factory(EntityTwo)().create()
const entityOne = await factory(EntityOne)().createMany(200, {
anotherField: entityTwo,
})
It fails. As I can see in src/entity-factory.ts (L91):
private async makeEnity(overrideParams: EntityProperty<Entity> = {}, isSeeding = false): Promise<Entity> {
if (this.factory) {
let entity = await this.resolveEntity(this.factory(Faker, this.context), isSeeding)
if (this.mapFunction) {
entity = await this.mapFunction(entity)
}
for (const key in overrideParams) {
if (overrideParams.hasOwnProperty(key)) {
entity[key] = overrideParams[key]
}
}
return entity
}
throw new Error('Could not found entity')
}
overrideParams is being checked AFTER persisting/creating entity. Is this the expected behaviour?
We can extrapolate this as if I override a param that is a factory with another previously created entity, the original value is still on DB. Imagine seeding the database with thousands of rows.
I will try to update the message to the last commit
private async makeEntity(overrideParams: EntityProperty<Entity> = {}, isSeeding = false): Promise<Entity> {
if (!this.factory) {
throw new Error('Could not found entity')
}
let entity = await this.resolveEntity(this.factory(Faker, this.context), isSeeding)
if (this.mapFunction) {
entity = await this.mapFunction(entity)
}
for (const key in overrideParams) {
if (overrideParams.hasOwnProperty(key)) {
entity[key] = overrideParams[key]
}
}
return entity
}
resolveEntity is creating/making some other entities that is related to the main entity, like this example:
define(EntityOne, (faker: typeof Faker) => {
const entity = new EntityOne()
const field2 = factory(EntityTwo)()
const field3 = factory(EntityThree)().create()
entity.title = faker.random.word()
entity.field2 = field2
entity.field3 = field3
return entity
})
field2 depends on seeding, but could be possible to be persisted. field3 is being persisted EVERY single time. This could cause some problems because if I try to create an entity this way:
await factory(EntityOne)().create({
field3: await factory(EntityThree)().create()
})
Two EntityThree are being created but only the second is related. This can cause problems with UNIQUE restrictions or GET requests that lists resources
@RaphaelWoude please take a look on this, i will update my PR