Wednesday, 25 May 2022

Seeding: how to link a created entity to another?

I use typeorm-seeding to seed my database handled by typeorm. I have 2 factories for 2 entities Customer and Event:

Entitites

// entity/Customer.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, ManyToMany, JoinTable, JoinColumn } from 'typeorm'
import { Event } from './Event'

@Entity()
export class Customer {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  firstname: string;

  @Column()
  lastname: string;

  @Column()
  email: string

  @ManyToMany(() => Event, event => event.customers, { cascade: true })
  @JoinTable()
  events: Promise<Event[]>
}


// entity/Event.ts
import { Entity, PrimaryColumn, Column, CreateDateColumn, OneToMany, ManyToMany, JoinTable, DeleteDateColumn } from 'typeorm'
import { Course } from './Course'
import { Customer } from './Customer'

@Entity()
export class Event {
  @PrimaryColumn()
  id: string;

  @Column()
  name: string;

  @ManyToMany(() => Customer, customer => customer.events)
  @JoinTable()
  customers: Promise<Customer[]>
}

Factories

// factory/event.ts
import { define, factory } from 'typeorm-seeding'

import { Event } from '../../entity/Event'

define(Event, (faker) => {
  const event = new Event()

  event.id = faker.company.bsBuzz()
  event.name = faker.company.catchPhraseNoun()
  event.date = faker.date.recent()

  return event
})


// factory/customer.ts
import { Customer } from '../../entity/Customer'

define(Customer, (faker) => {
  const customer = new Customer()

  customer.firstname = faker.name.firstName()
  customer.lastname = faker.name.lastName()
  customer.email = faker.internet.email()

  return customer
})

As you can see a Customer can have multiple Events and different Customers can participate to the same Event. So my goal for the seeding part is to create 10 different Events and then create 100 Customers that participate at some of these Events. So I created 2 seeding files:

// seed/create-events.ts
import { Factory, Seeder } from 'typeorm-seeding'
import { Event } from '../entity/Event'

export default class CreateEvents implements Seeder {
  public async run(factory: Factory): Promise<any> {
    await factory(Event)().createMany(10)
  }
}


// seed/create-customers.ts
import { Factory, Seeder } from 'typeorm-seeding'
import { Customer } from '../entity/Customer'

export default class CreateCustomers implements Seeder {
  // eslint-disable-next-line class-methods-use-this
  public async run(factory: Factory): Promise<any> {
    await factory(Customer)().createMany(100)
  }
}

However that only create some entries but doesn't link them together.

I know that I could use the Event's factory inside of the the Customer's one:

// factory/customer.ts
import { Customer } from '../../entity/Customer'

define(Customer, (faker) => {
  const customer = new Customer()

  customer.firstname = faker.name.firstName()
  customer.lastname = faker.name.lastName()
  customer.email = faker.internet.email()

  customer.events = factory(Event)().createMany(10)

  return customer
})

But that will just create 10 different Events for each Customer.

So how to seed my Customers in a way that they are linked to some Events created during the seed:run command?



from Seeding: how to link a created entity to another?

No comments:

Post a Comment