Skip to content

createTypeOrmProviders should inject EntityManager instead of Connection #1819

Closed
@edeesis

Description

@edeesis

Is there an existing issue that is already proposing this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe it

createTypeOrmProviders currently injects getConnection and resolves the repositories directly from the connection. However, there are certain scenarios when you'd want to resolve the repository from the EntityManager, such as when running in a transaction.

Describe the solution you'd like

I'm proposing changing the createTypeOrmProviders function to inject the EntityManager and use that to initialize the repositories.

export function createTypeOrmProviders(
  entities?: EntityClassOrSchema[],
  dataSource?: DataSource | DataSourceOptions | string,
): Provider[] {
  return (entities || []).map((entity) => ({
    provide: getRepositoryToken(entity, dataSource),
    useFactory: (entityManager: EntityManager) => {
      const enitityMetadata = dataSource.entityMetadatas.find((meta) => meta.target === entity)
      const isTreeEntity = typeof enitityMetadata?.treeType !== 'undefined'
      return isTreeEntity 
        ? entityManager.getTreeRepository(entity)
        : entityManager.connection.options.type === 'mongodb'
          ? entityManager.getMongoRepository(entity)
          : entityManager.getRepository(entity);
    },
    inject: [getEntityManagerToken(dataSource)],
    /**
     * Extra property to workaround dynamic modules serialisation issue
     * that occurs when "TypeOrm#forFeature()" method is called with the same number
     * of arguments and all entities share the same class names.
     */
    targetEntitySchema: getMetadataArgsStorage().tables.find(
      (item) => item.target === entity,
    ),
  }));
}

Teachability, documentation, adoption, migration strategy

This should theoretically be a non-breaking change to all users of the library. We're merely changing which object we're calling getRepository on. In fact, DataSource's getRepository method just proxies to the manager anyway.

What is the motivation / use case for changing the behavior?

The instance of manager changes when you open a transaction. That manager instance has to be used to generate the repository, otherwise the transaction is ignored.

Currently, the only method for working around this is overriding each Repository provider. This would allow someone to override the EntityManager and then all repositories created will use that manager instance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions