如何在 nestjs 中为 typeorm 自定义存储库创建工厂?

How to create a factory for a typeorm custom repository in nestjs?

我有一个存储库:

export class MyRepository 
    extends 
        Repository<MyEntity>
{

constructor(
        protected readonly _clientId: string
    ) {
        super()
    }

 // ... methods
}

我需要传递直到请求时才知道的客户端 ID。因此,我知道该怎么做的唯一方法是创建一个可以在 运行 时间创建 repo 的工厂(它在 GRPC 元数据中)。

@Injectable()
export class MyRepositoryFactory {
    create(clientId: string) {
        return new MyRepository(
            clientId,
        );
    }
}

我将其注册为提供商,然后在我的控制器中调用:

const { clientId } = context;
const repository = this.myRepositoryFactory.create(clientId);

但是我得到了错误

"Cannot read property 'findOne' of undefined"

尝试进行基本的 typeorm 调用时。我可以看到这是因为存储库应该在模块导入中注册,例如:

imports: [
    TypeOrmModule.forFeature([ MyRepository, MyEntity ])
  ],

然而,这仅在直接注入存储库时有效,而不是在工厂中。我不知道如何克服这个问题,或者使用不同的方式在 运行 时间创建存储库,并传递 GRPC 元数据。如有任何帮助,我们将不胜感激。

您无法调用 new 并将存储库连接到 TypeORM。
为此,您需要调用 getCustomRepository(MyCustomRepository(或 connectio.getCustomRepository),以便它连接到 connectiong 池以及 TypeORM 隐藏在引擎盖下的所有内容。

IMO 根据请求创建自定义存储库并不是一个好主意,也许您可​​以创建一个范围为 REQUESTProvider(因此将创建提供者 per-request)允许 NestJS 以 'standard' 方式注入存储库,修改它的客户端属性,然后使用它使用内部存储库方法的方法。

@Injectable({ scope: Scope.REQUEST })
export class RequestRepositoryHandler {
  client_id: string
  
  constructor(@InjectRepository(MyEntity) private repo: Repository<MyEntity>){}

  // other methods
}

// usage
@Injectable()
export class SomeService {
  constructor(private providerRepo: RequestRepositoryHandler){}

  async method(client_id: string){
    this.providerRepo.client_id = client_id; // the provider is per-request
    // now do some work
  }
}