Situation:
Pour notre SaaS nous utilisons multitenancy basé sur un schéma , ce qui signifie que chaque client (~ locataire) a son propre schéma dans le même (postgres), sans interférer avec les autres clients. Chaque schéma se compose du même modèle d'entité sous-jacent.
Chaque fois qu'un nouveau client est enregistré sur le système, un nouveau schéma isolé est automatiquement créé dans la base de données. Cela signifie que le schéma est créé au moment de l'exécution et n'est pas connu à l'avance. Le schéma du client est nommé en fonction du domaine du client.
Pour chaque demande qui parvient à notre API, nous extrayons l'affiliation de location de l'utilisateur du JWT et déterminons le schéma de base de données à utiliser pour effectuer les opérations de base de données demandées pour ce locataire.
Problème
Après avoir établi une connexion à une base de données (postgres) via TypeORM (par exemple en utilisant createConnection ), notre seule chance de définir le schéma d'une opération db est de recourir à la createQueryBuilder
:
const orders = await this.entityManager
.createQueryBuilder()
.select()
.from(`${tenantId}.orders`, 'order') // <--- setting schema-prefix here
.where("order.priority = 4")
.getMany();
Cela signifie que nous sommes obligés d'utiliser le QueryBuilder
car il ne semble pas possible de définir le schéma lorsque vous travaillez avec API EntityManager (ou API du référentiel ).
Cependant, nous voulons/devons utiliser ces API, car elles sont beaucoup plus simples à écrire, nécessitent moins de code et sont également moins sujettes aux erreurs, car elles ne reposent pas sur l'écriture de requêtes "manuellement" en utilisant une syntaxe basée sur des chaînes.
Question
Dans le cas de TypeORM, est-il possible de définir le schéma db d'une manière ou d'une autre lorsque vous travaillez avec EntityManager
ou les référentiels?
Quelque chose comme ça?
// set schema when instantiating manager
const manager = connection.createEntityManager({ schema: tenantDomain });
// should find all matching "order" entities within schema
const orders = manager.find(Order, { priority: 4 })
// should find a matching "item" entity within schema using same manager
const item = manager.findOne(Item, { id: 321 })
Remarques:
Pour répondre à ma propre question:
Pour le moment, il n'y a aucun moyen d'instancier référentiels TypeORM avec différents schémas au moment de l'exécution sans créer de nouvelles connexions.
Ainsi, les deux seules options qui restent à un développeur pour la multi-location basée sur un schéma sont:
createQueryBuilder
(ou exécuter des requêtes SQL via query()
).Pour de plus amples recherches, voici quelques problèmes de TypeORM GitHub qui suivent l'idée de changer le schéma d'une connexion ou d'un référentiel existant au moment de l'exécution (similaire à ce qui est demandé dans l'OP):
this.photoRepository.useSchema('customer1').find()
getConnection().changeDefaultSchema('myschema')
P.S. Si TypeORM décide de soutenir l'idée discutée dans le PO, je vais essayer de mettre à jour cette réponse.