播种时NestJS中的TypeOrm:RepositoryNotFoundError

Posted

技术标签:

【中文标题】播种时NestJS中的TypeOrm:RepositoryNotFoundError【英文标题】:TypeOrm:RepositoryNotFoundError in NestJS while seeding 【发布时间】:2020-07-10 01:10:23 【问题描述】:

我正在尝试使用 NestJS 和 TypeORM 为我的数据库播种。

我有一个创建exercise 表的迁移文件和一个将ExerciseEntity 插入表中的种子文件。这些文件的主要区别在于迁移文件直接运行查询:

public async up(queryRunner: QueryRunner): Promise<any> 
  await queryRunner.query(
    `CREATE TABLE ...`
  );

当种子文件获取存储库时:

public async up(queryRunner: QueryRunner): Promise<any> 
  await queryRunner.manager.getRepository<ExerciseEntity>(ExerciseEntity).save(
    someExerciseEntity
  );

这个getRepository 是造成错误的人。

RepositoryNotFoundError: No repository for "ExerciseEntity" was found. Looks like this entity is not registered in current "default" connection?
    at new RepositoryNotFoundError (C:\Users\Dev\Documents\team-management\src\error\RepositoryNotFoundError.ts:10:9)
    at EntityManager.getRepository (C:\Users\Dev\Documents\team-management\src\entity-manager\EntityManager.ts:1194:19)
    at SeedExercises1584903747780.<anonymous> (C:\Users\Dev\Documents\team-management\dist\apps\api\_seeds\dev\webpack:\_seeds\dev\1584903747780-SeedExercises.ts:7:31)

在一项服务中,我获得了存储库并毫无问题地保存了实体。该问题仅在播种时发生。

我注册TypeORM如下:

// app.module.ts
@Module()
export class AppModule implements NestModule 
  static forRoot(): DynamicModule 
    return 
      module: AppModule,
      imports: [
        ConfigModule.forRoot(
          envFilePath: '.env.dev',
          validationSchema: validationSchema()
        ),
        TypeOrmModule.forRootAsync(
          imports: [ConfigModule],
          inject: [ConfigService],
          useFactory: async (configService: ConfigService) => databaseProviders(configService)
        ),
        ExercisesModule.forRoot()
      ]
    ;
  

地点:

// database.provider.ts
export const databaseProviders = (configService: ConfigService) => 
  const normalizePath = (_path: string) => (path.normalize(path.join(__dirname, _path)));

  const commonDB: TypeOrmModuleOptions = 
    type: 'sqlite',
    entities: [...exercisesEntities]
  ;
  // exerciseEntities comes from an index.ts in an exercise library
  // import  ExerciseEntity  from './exercise.entity';
  // export const exercisesEntities = [ExerciseEntity];

  const defaultDB: TypeOrmModuleOptions = 
    ...commonDB,
    database: path.join(
      configService.get('APP_ROOT_PATH', '.'),
      configService.get('TYPEORM_DATABASE', 'gym-dev.sqlite')
    ),
    logging: configService.get<boolean>('TYPEORM_ENABLE_LOGGING', true) ? ['query', 'error'] : [],
    cache: true,
    synchronize: configService.get<boolean>('TYPEORM_SYNCHRONIZE', false),
    migrations: [normalizePath('_migrations/*.js'), normalizePath('_seeds/dev/*.js')],
    migrationsRun: configService.get<boolean>('TYPEORM_MIGRATIONS_RUN', true),
    dropSchema: configService.get<boolean>('DROP_SCHEMA', false)
  ;

  return defaultDB;
;

我正在使用nrwl/nx 使用以下 webpack 配置编译和提供应用程序:

module.exports = function(config, context) 
  const baseDirectory = path.resolve(config.output.path);

  const entityPaths = ['libs/feature/api/**/entities/*.js'];
  const migrationPaths = ['_migrations/*.js', '_seeds/**/*.js'];
  config.entry = 
    ...config.entry,
    ...getEntityEntries(entityPaths),
    ...getMigrationEntries(migrationPaths)
  ;
  // getEntries functions allows the compilation of entities and migrations

  // Output
  config.output = 
    path: baseDirectory,
    filename: '[name].js',
    libraryTarget: 'commonjs'
  ;

  return config;
;

我的dist 结构最终是:

dist
|-apps
  |-api
    |-_migrations  // contains compiled migrations
    |-_seeds       // contains compiled seeders
    |-lib
      |-entities   // contains compiled entities
    |-main.js

正如app.module.ts 中所见,我正在使用TypeOrmModule.forRootAsync 来注入配置服务。我怀疑也许当播种者被执行时,存储库还没有注册。这将解释稍后在运行 Web 应用程序时,服务可以访问存储库。

知道如何解决这个问题吗? 我的配置是错误的还是遗漏了什么?如果这是问题所在,播种器中是否有办法等待存储库被注册?

编辑: 它与TypeOrmModule.forRootAsync 没有任何关系。我做了以下更改:

// app.module.ts
@Module()
export class AppModule implements NestModule 
  static forRoot(): DynamicModule 
    return 
      module: AppModule,
      imports: [
        ConfigModule.forRoot(
          envFilePath: '.env.dev',
          validationSchema: validationSchema()
        ),
        TypeOrmModule.forRoot(databaseProvidersSync()),
        ExercisesModule.forRoot()
      ]
    ;
  

// database.providers.ts
export const databaseProvidersSync = () => 
  const normalizePath = (_path: string) => (path.normalize(path.join(__dirname, _path)));
  const defaultDB: TypeOrmModuleOptions = 
    type: 'sqlite',
    entities: [...exercisesEntities],
    database: path.normalize(`C:\\Users\\Dev\\Documents\\team-management\\gym-dev.sqlite`),
    logging: ['query', 'error'],
    cache: true,
    synchronize: false,
    migrations: [normalizePath('_migrations/*.js'), normalizePath('_seeds/dev/*.js')],
    migrationsRun: true,
    dropSchema: true
  

  return defaultDB;

而且错误是一样的。

【问题讨论】:

【参考方案1】:

问题来自当前的 TypeORM 版本(0.2.24)。

我切换到 0.2.22 并且它工作正常,没有更改任何其他内容。

这是我用这段文字打开的问题,最后问他们希望什么时候修复它: https://github.com/typeorm/typeorm/issues/5781 而这里的一些问题似乎在上个版本中谈到了这个问题:https://github.com/typeorm/typeorm/issues/5676

【讨论】:

非常感谢。这也为我解决了这个问题。我已经浪费了几个小时来敲我的头,似乎截至 0.2.34 这个问题还没有解决。

以上是关于播种时NestJS中的TypeOrm:RepositoryNotFoundError的主要内容,如果未能解决你的问题,请参考以下文章

NestJS + TypeORM 中的 JoinTable 问题

Nestjs 与自定义存储库中的 Typeorm 事务

TypeORM/NestJS 中的分页

我在用 typeorm 编译 Nestjs 时出错

什么是 nestjs typeorm 中的 getRepositoryToken 以及何时使用它?

NestJS & TypeORM:发布请求中的 DTO 格式