NestJS 延迟加载导入 TypeORM 的模块不注册“连接”提供程序

Kap*_*ash 2 lazy-loading typeorm nestjs

我有一个DatabaseModule导入 TypeORM 并启动数据库连接(参见database.module.ts)。我在 CRUD 模块上使用该模块,并且在以经典方式注册模块时一切正常。

但是,当我延迟加载同一模块时,它会中断并出现“无法解析连接”错误。

“错误 [ExceptionsHandler] Nest 无法解析 ProductRepository 的依赖关系(?)。请确保索引 [0] 处的参数 Connection 在 TypeOrmModule 上下文中可用。”

我正在编写无服务器函数,因此尝试延迟加载。

// product.module.ts: the module I lazy-load
@Module({
imports: [
  DatabaseModule.register({
    entities: [Product],
  }),
],
Run Code Online (Sandbox Code Playgroud)
// database.module.ts: the module that creates the db connections
export interface DatabaseOptions {
  entities: any[];
}

@Module({})
export class DatabaseModule {
  static register(options: DatabaseOptions): DynamicModule {
    return {
      module: DatabaseModule,
      imports: [
        TypeOrmModule.forRoot({
          type: 'mysql',
          host: '0.0.0.0',
          port: 3306,
          username: 'root',
          password: '****',
          database: 'example',
          retryAttempts: 5,
          synchronize: true,
          entities: options.entities,
        }),
        TypeOrmModule.forFeature(options.entities),
      ],
      providers: [],
      exports: [TypeOrmModule],
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

这是延迟加载部分。

// app.controller.ts
@Get()
async createProduct(): Promise<Product> {
  // Lazy load the module that imports the DatabaseModule to lazy-load the connections.
  const { ProductModule } = await import('./product/product.module');
  const productModule = await this.lazyModuleLoader.load(() => ProductModule);
  const { ProductService } = await import('./product/product.service');
  // It breaks here, 'Connection' providers are not registered.
  const productService = productModule.get(ProductService);

  return productService.create();
}
Run Code Online (Sandbox Code Playgroud)

再次,当我在 main 中注册时它工作得很好ProductModuleAppModule,所以我希望该模块能够以与延迟加载相同的方式工作

我想我必须延迟加载更多的东西才能工作,但我无法理解为什么当我延迟加载产品模块时连接/存储库提供程序不可用......

复制存储库 (有一个带有 mysql 映像的 docker-compose 可以在本地调试)。

小智 5

不幸的是,我遇到了同样的问题。我已经通过提供商让它工作了ASYNC_CONNECTION

import { ConnectionOptions, createConnection, getConnection } from 'typeorm';

providers: [{
  provide: 'ASYNC_CONNECTION',
  inject: [ConfigService],
  useFactory: async (configService: ConfigService) => {
    const { host, port, username, password, database } = configService.get('db');

    const connection: ConnectionOptions = {
      type: 'postgres',
      host,
      port,
      username,
      password,
      database,
      name: 'custom',
      entities: [...entities],
      synchronize: false,
      namingStrategy: new SnakeNamingStrategy(),
    };

    try {
      getConnection(connection.name);
    } catch (error) {
      return await createConnection(connection);
    }
  }
}]
Run Code Online (Sandbox Code Playgroud)

然后你可以在任何你想要的地方注入ASYNC_CONNECTION提供者:

@Inject('ASYNC_CONNECTION')
private connection: Connection,
Run Code Online (Sandbox Code Playgroud)

并对上面声明的实体使用经典的存储库方法:

this.connection.getRepository(<Entity>).findOne({})
Run Code Online (Sandbox Code Playgroud)

就是这样。