TypeORM:在运行时为 EntityManager(或存储库)动态设置数据库架构?

TypeORM: Dynamically set database schema for EntityManager (or repositories) at runtime?

情况:

对于我们的 SaaS API,我们在同一个 (postgres) 数据库中使用 schema-based multitenancy, which means every customer (~tenant) has its own separate schema,不会干扰其他客户。每个模式都包含相同的底层实体模型。

每次新客户注册到系统时,都会在数据库中自动创建一个新的独立模式。这意味着,模式是在运行时创建的,事先不知道。客户的架构根据客户的域命名。

对于到达我们 API 的每个请求,我们从 JWT 中提取用户的租户隶属关系,并确定使用哪个数据库模式来为该租户执行请求的数据库操作。

问题

通过 TypeORM (e.g. using createConnection) 建立到 (postgres) 数据库的连接后,我们为数据库操作设置模式的唯一机会是求助于 createQueryBuilder:

const orders = await this.entityManager
  .createQueryBuilder()
  .select()
  .from(`${tenantId}.orders`, 'order') // <--- setting schema-prefix here
  .where("order.priority = 4")
  .getMany();

这意味着,我们被迫使用 QueryBuilder,因为在使用 EntityManager API (or the Repository API) 时似乎无法设置模式。

但是,我们 want/need 使用这些 API,因为它们编写起来更简单,需要的代码更少,也更不容易出错,因为它们不依赖于编写查询"manually" 采用基于字符串的语法。

问题

对于 TypeORM,在使用 EntityManager 或存储库时是否可以以某种方式设置数据库模式?

是这样的吗?

// 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 })

备注:

由于评论对我不起作用,这里是 NestJS 文档中的提示:

https://docs.nestjs.com/techniques/database#async-configuration

我没有使用 NestJS,但目前正在阅读文档来决定它是否适合我们。我们有一个应用程序,其中只有一些模块具有每个租户模式的多租户,所以使用 TypeOrmModule.forRootAsync(dynamicCreatedDbConfig) 对我来说也是一个选择。

如果您有拦截器或中间件,这可能会对您有所帮助,它会在...之前准备 dynamicCreatedDbConfig 数据...

回答我自己的问题:

目前无法在不创建新连接的情况下在运行时使用不同的模式实例化 TypeORM repositories

因此,对于基于模式的多租户,开发人员仅有的两个选择是:

  1. 设置新连接以在运行时连接同一数据库中的不同模式。例如。参见 . However, one should definitely strive for reusing connections and and be aware of connection limits
  2. 放弃使用 RepositoryApi 的想法并恢复使用 createQueryBuilder(或通过 query() 执行 SQL 查询)。

为了进一步研究,这里有一些 TypeORM GitHub 问题跟踪在运行时更改现有连接或存储库的架构的想法(类似于 OP 中的请求):

P.S。如果 TypeORM 决定支持 OP 中讨论的想法,我将尝试更新此答案。

这里是 global overview 的 schema-based 多租户问题以及完整的演练 Github 存储库。

大多数时候,您可能想改用 Postgres Row Security Policy。它提供了 schema-based 多租户的大部分好处(尤其是在开发人员体验方面),而没有与连接倍增相关的问题。