symfony / symfony-docs

The Symfony documentation
https://symfony.com/doc
Other
2.16k stars 5.11k forks source link

With multiple Entity Managers (EM) the Repository uses only the mapped EM for the Entity #9878

Closed bigs21 closed 3 years ago

bigs21 commented 6 years ago

In the manual page How to Work with multiple Entity Managers and Connections for Symfony 4, we can see in the end the following code snippet:

        // Retrieves a repository managed by the "customer" em
        $customers = $this->getDoctrine()
            ->getRepository(Customer::class, 'customer')
            ->findAll()
        ;

Using the ORM configuration code indicated in the beginning of that document, where the Customer entity is mapped to the 'customer' entity manager, the 'customer' parameter for the getRepository() method is ignored. As so, this last code about repository calls should be updated.

Also, I suggest to add the code on how to use multiple entity managers for a single Entity, or to add a note that it's not possible if that's the case.

xabbuh commented 6 years ago

If this is not working as described, the issue should be reported to the Doctrine issue tracker where the implementing code is located. Though actually I do not see why that should not be working as described.

bigs21 commented 6 years ago

Well, after all, it was, as after a few more tests I found out that I had an issue with where the Entities were placed: instead of having them in 'src/Entity/Main' and 'src/Entity/Customer', I had them in 'src/Entity' and 'src/EntityCustomer', with them being configured in that order.

With that, Doctrine was mapping the customer entities to the first (and default) entity manager.

Anyway, from what I've found out that the second parameter to getRepository is currently ignored, as there's no such parameter (is this from a previous version of symfony?).

As so, we can say the following:

        // Retrieves a repository managed by the "customer" em, the Customer's entity em
        $customers = $this->getDoctrine()
            ->getRepository(Customer::class)
            ->findAll()
        ;

        // Retrieves a repository managed by the "customer" em
        $customers = $this->getDoctrine()
            ->getRepository(Customer::class, 'customer')
            ->findAll()
        ;

So, the entity manager used in the repository is always the mapped one of that Entity, and by mapping the entities to a given em, we can't change a different connection to access some Entity, as it will only use the connection for it's em. That comes from a use case where we were trying to use different connections (different databases) to access the same Entity (the same table structure), but in the same request always use the same connection. For example, depending on some parameter the request would use connection_A or connection_B.

I propose to add a note in the page specifying that it's not possible to use different entity managers to access the same Entity.

javiereguiluz commented 6 years ago

@xabbuh what do you propose to do here? If it's true that getRepository() ignores the second argument ... shouldn't we just remove the second example? Thanks!

xabbuh commented 6 years ago

Yes, I think we shouldn't have it.

delorie commented 6 years ago

Hello,

A brief introduction to our system: The mission: we want to import data from a MSSQL database into our new application.

We have a vagrantbox, in there running the new application. And a docker for the MSSQL database. Now we have an Import Symfony Command Script on hostsystem that connects to the MSSQL database (Docker) and to the Maria database (Vagrantbox) via SSH 3333:172.0.0.1:3306.

Our Doctrine Config

doctrine:
    dbal:
        default_connection: default
        types:
            uuid_binary_ordered_time: Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType
        connections:
            default:
                # configure these for your database server
                driver: 'pdo_mysql'
                [...]
                url: '%env(resolve:DATABASE_URL)%' # Port 3306
                [...]
            command:
                driver: 'pdo_mysql'
                [...]
                url: '%env(resolve:COMMAND_DATABASE_URL)%' # Port 3333
                [...]

    orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        [...]
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    App:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity'
                        alias: App
            command:
                connection: command
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    App:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity'
                        alias: AppCommand

In our Command Script:

$doctrine = $this->container->get('doctrine');
$doctrine->getRepository(Salutation::class, 'command')->findAll()

// But Doctrine use the default EntityManager

We found in this File: vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/AbstractManagerRegistry.php Doctrine\Common\Persistence\AbstractManagerRegistry

The method "getManagerForClass" ignores the defindet connection getManagerForClass() (Line: 156) [...]

foreach ($this->managers as $id) {
    $manager = $this->getService($id);

    if (! $manager->getMetadataFactory()->isTransient($class)) { // <-- first goal 
        return $manager;
    }
}

```php
[...]

// Debug output
$this = {Doctrine\Bundle\DoctrineBundle\Registry} [7]
...
 *Doctrine\Common\Persistence\AbstractManagerRegistry*managers = {array} [2]
  default = "doctrine.orm.default_entity_manager" // <-- first goal 
  command = "doctrine.orm.command_entity_manager"
...

The problem is just by Entitys with defined CustomRepositorys
```php
/**
 * @ORM\Table(name="salutations")
 * @ORM\Entity(repositoryClass="App\Repository\Person\SalutationRepository") // <-- Without CustomRepository it works
 */
class Salutation {}

Without CustomRepository it works because the Method "getRepository" in Class "ContainerRepositoryFactory" found no a $customRepositoryName so the call

return $this->getOrCreateRepository($entityManager, $metadata); (Line 77) // this works finde

but have the method found a CustomRepository the call $repository = $this->container->get($customRepositoryName);

pouetman87 commented 5 years ago

is there any news regarding the resolution of this issue?

T123mutouren commented 5 years ago

关于解决这个问题的消息有什么消息吗?

andrmoel commented 5 years ago

Just don't use a custom repository. This will work. But IMHO that's no solution. Its a bug, which should be fixed.

m2payco commented 5 years ago

I'm in the same situation. I want to use another entity manager to connect to a read-only replica of the original database using the same entities.

pouetman87 commented 5 years ago

the only way that i found to use both custom repositories and more than one database is to use symfony version 3.4

Floeig commented 5 years ago

So far I have found this temporary solution for Symfony4

 private $registry;
    public function __construct(RegistryInterface $registry)
    {
        $this->registry = $registry;
        //parent::__construct($registry, MyEntity::class);
    }

    public function findAllByFieldName($customFieldName, $connection): array
    {
        $em = $this->registry->getEntityManager($connection);

        $customFields = $em->getRepository(MyEntity::class)->findOneBy(['Field_name'=>$customFieldName]);
   /* ...... */
}

Ugly but works..

tech-no-logical commented 5 years ago

this issue just cost me about a day's worth of debugging (I'm just starting out with symfony/doctrine so it took a while). together with a colleague we came to this workaround (we have two types of users, each with its own repositry and entitymanager)

namespace App\Repository;

use App\Entity\CustomUser;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Doctrine\ORM\EntityRepository;

class CustomUserRepository extends AbstractUserRepository
{
    public function __construct(RegistryInterface $registry)
    {
        $manager = $registry->getEntityManager('namedentitymanager');

        parent::__construct($registry, CustomUser::class);
        EntityRepository::__construct($manager, $manager->getClassMetadata(CustomUser::class));
    }
}

the thought being that the parent::construct() puts in the default entity manager (the wrong one). the call to EntityRepository::construct() fixes this.

broiniac commented 5 years ago

Today I've run into similar problem. Long story short - I want to copy data from database no2 into database no1. Both are using same code base.

@andrmoel is right - only solution for now is to not use custom repositories.

The fastest way will be to use QueryBuilder: https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/query-builder.html#constructing-a-new-querybuilder-object

In another words - don't user getRepository method.

Example:

// get EntityManagers you want to use
$emTo = $registry->getManager();            // manager connected to "main" database
$emFrom = $registry->getManager('migrate'); // manager connected to other database

// create QueryBuilder for Entity from 'migrate' database
$emFrom->createQueryBuilder()
    ->select('a')
    ->from('App\Entity\Article', 'a')
;

// add some regular methods and conditions next

It looks easy (because it is) and obvious, but it wasn't easy to figure it out. Thank you guys for help!

r2my commented 5 years ago

Hi! any news regarding this issue? I tried with Symfony 4.3.0, same issue... Thanks for your help!

xabbuh commented 5 years ago

Can someone create a small example application that allows to debug? I would like to find out whether that's an issue in the documentation, in Symfony or in Doctrine, but I don't have such a use case in any of my applications.

r2my commented 5 years ago

Hi! I created a new installation here: https://github.com/r2my/symfomem There are 3 EM: main, customer01 and customer02. In ProductController, you'll see that 'customer01' and 'customer02' in getRepository() method are ignored.

ekdevcenter commented 5 years ago

config/packages/doctrine.yaml

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                # configure these for your database server
                url: '%env(DATABASE_DB1_URL)%'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4
            offerbdd:
                # configure these for your database server
                url: '%env(DATABASE_DB2_URL)%'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4

    orm:
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                mappings:
                    App:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity\'
                        alias: App
            offerbdd:
                connection: offerbdd
                mappings:
                    Offer:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity\'
                        alias: Offer

My Repository

namespace App\Repository;

use App\Entity\Offer;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;

/**
 * @method Offer|null find($id, $lockMode = null, $lockVersion = null)
 * @method Offer|null findOneBy(array $criteria, array $orderBy = null)
 * @method Offer[]    findAll()
 * @method Offer[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class OfferRepository extends ServiceEntityRepository
{
    private $registry;

    public function __construct(RegistryInterface $registry)
    {
        $this->registry = $registry;
    }
    /**
     * @return mixed
     */
    public function findListedAll($connection)
    {
        $sql = "SELECT o FROM App\Entity\Offer o WHERE o.unlisted = :val OR o.unlisted IS NULL "
             . "ORDER BY o.id DESC";

        return $this->registry->getEntityManager($connection)
            ->createQuery($sql)
            ->setParameter('val', false)
            ->getResult();
    }
}

My Controller:

public function index(Request $request)
    {
    ...
            $offerEntityManager  = $this->getDoctrine()->getManager('offerbdd');
            $offers = $offerEntityManager->getRepository(Offer::class)->findListedAll('offerbdd');
        ....
    }

It's work! Thanks to you tech-no-logical and to others for their contribution. It helped me a lot.

soeren-helbig commented 5 years ago

Hey! Same here. Ended up in removing repositoryClass from mapping, but it feels a very strange!

Edit: another possible workaround

ArticleRepository extends ServiceEntityRepository
{
    ...
    public function setEntityManager(EntityManagerInterface $entityManager): self
    {
        $this->_em = $entityManager;

        return $this;
    }
   ....
}

e.g.

$activeEntityManager = ...;

$articles = $activeEntityManager
    ->getRepository('App:Article')
    ->setEntityManager($activeEntityManager)
    ->findAll()
;

@xabbuh for me it seems to be doctrine issue. Some debugging brought me to the same point as @delorie already showed in his post.

OskarStark commented 5 years ago

@xabbuh did you already find some time to try the reproducer mentioned in https://github.com/symfony/symfony-docs/issues/9878#issuecomment-498207781 ?

xabbuh commented 5 years ago

The example application didn't make use of the getRepository() method of the ManagerRegistry, but called the getRepository() method of a concrete entity manager instead. This cannot work as that method doesn't have the manager name argument.

However, if we change the code to actually use the manager registry, we will see no difference in the behaviour. This comes from the fact that ContainerRepositoryFactory class that is used behind the scenes will only find one service for the repository class. If we further changed the code to let the repository not extend the ServiceEntityRepository, we will finally see a change in the behaviour.

ipernet commented 5 years ago

I'm replying here on the subject of having multiple entity managers managing the same entities and the bug related to it.

However, if we change the code to actually use the manager registry, we will see no difference in the behaviour. This comes from the fact that ContainerRepositoryFactory class that is used behind the scenes will only find one service for the repository class. If we further changed the code to let the repository not extend the ServiceEntityRepository, we will finally see a change in the behaviour.

Agreed with the description @xabbuh but as @andrmoel said, we can consider there is still a bug here, because there is a different behavior based on whether the entity is defined with a custom repository and how this one is defined or whether no custom repository is used.

It's subtle because if the entity uses a custom repository extending the EntityRepository class, the behavior is different than if the repo extends the newer ServiceEntityRepository class.

Here is a repro project: https://github.com/ipernet/symfony-doctrine-multi-em-test

And the test command:

<?php

namespace App\Command;

use App\Entity\Cat;
use App\Entity\Dog;
use App\Entity\Duck;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\Common\Persistence\ManagerRegistry;

class SameEntityDualManagerCommand extends Command
{
    // the name of the command (the part after "bin/console")
    protected static $defaultName = 'app:test';

    /**
     * @var ManagerRegistry
     */
    private $registry;

    public function __construct(ManagerRegistry $registry)
    {
        $this->registry = $registry;
        $this->defautEm = $this->registry->getManager('default');
        $this->otherEm = $this->registry->getManager('em2');

        parent::__construct();
    }

    protected function configure()
    {
        // ...
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->output = $output;

        $this->testEntityWithNoCustomRepository();
        $this->testEntityWithNoCustomRepositoryUsingRegistryRepository();

        $this->testEntityWithCustomRepositoryExtendingServiceEntityRepository();
        $this->testEntityWithCustomRepositoryExtendingServiceEntityRepositoryUsingRegistryRepository();

        $this->testEntityWithCustomRepositoryExtendingEntityRepository();
        $this->testEntityWithCustomRepositoryExtendingEntityRepositoryUsingRegistryRepository();
    }

    /**
     *
     * @return void
     */
    private function testEntityWithNoCustomRepository()
    {
        $entityDefaultEm = $this->defautEm->getRepository(Dog::class)->findOneBy(['id' => 1]);
        $entityEm2 = $this->otherEm->getRepository(Dog::class)->findOneBy(['id' => 1]);

        $this->testResult($entityDefaultEm, $entityEm2);
        $this->output->writeln(' - '.__FUNCTION__);
    }

    /**
     *
     * @return void
     */
    public function testEntityWithNoCustomRepositoryUsingRegistryRepository()
    {
        $entityDefaultEm = $this->registry->getRepository(Dog::class, 'default')->findOneBy(['id' => 1]);
        $entityEm2 = $this->registry->getRepository(Dog::class, 'em2')->findOneBy(['id' => 1]);

        $this->testResult($entityDefaultEm, $entityEm2);
        $this->output->writeln(' - '.__FUNCTION__);
    }

    /**
     * @return void
     */
    private function testEntityWithCustomRepositoryExtendingServiceEntityRepository()
    {
        $entityDefaultEm = $this->defautEm->getRepository(Cat::class)->findOneBy(['id' => 1]);
        $entityEm2 = $this->otherEm->getRepository(Cat::class)->findOneBy(['id' => 1]);

        $this->testResult($entityDefaultEm, $entityEm2);
        $this->output->writeln(' - '.__FUNCTION__);
    }

    /**
     *
     * @return void
     */
    public function testEntityWithCustomRepositoryExtendingServiceEntityRepositoryUsingRegistryRepository()
    {
        $entityDefaultEm = $this->registry->getRepository(Cat::class, 'default')->findOneBy(['id' => 1]);
        $entityEm2 = $this->registry->getRepository(Cat::class, 'em2')->findOneBy(['id' => 1]);

        $this->testResult($entityDefaultEm, $entityEm2);
        $this->output->writeln(' - '.__FUNCTION__);
    }

    /**
     *
     * @return void
     */
    public function testEntityWithCustomRepositoryExtendingEntityRepository()
    {
        $entityDefaultEm = $this->defautEm->getRepository(Duck::class)->findOneBy(['id' => 1]);
        $entityEm2 = $this->otherEm->getRepository(Duck::class)->findOneBy(['id' => 1]);

        $this->testResult($entityDefaultEm, $entityEm2);
        $this->output->writeln(' - '.__FUNCTION__);
    }

    /**
     *
     * @return void
     */
    public function testEntityWithCustomRepositoryExtendingEntityRepositoryUsingRegistryRepository()
    {
        $entityDefaultEm = $this->registry->getRepository(Duck::class, 'default')->findOneBy(['id' => 1]);
        $entityEm2 = $this->registry->getRepository(Duck::class, 'em2')->findOneBy(['id' => 1]);

        $this->testResult($entityDefaultEm, $entityEm2);
        $this->output->writeln(' - '.__FUNCTION__);
    }

    private function testResult($entityDefaultEm, $entityEm2)
    {
        if (spl_object_hash($entityDefaultEm) === spl_object_hash($entityEm2)) {
            $this->output->write('<error>NOT OK: The two entities should not be the same object</error>');
        } else {
            $this->output->write('<info>OK: The two entities are different objects</info>');
        }
    }
}

image

OskarStark commented 5 years ago

Sorry for bothering you Andreas (@alcaeus ), but can you please have a look at this issue and the reproducers and may support us here? Thanks 🙏 🍺

alcaeus commented 5 years ago

No problem. Without reading through the entire issue, there used to be an issue in the manager registry where calling getRepository did not call getManagerForClass: https://github.com/doctrine/persistence/issues/45. This was fixed in https://github.com/doctrine/persistence/pull/48 which was released in 1.1.1 back in April. With this fixed, calling $this->getDoctrine()->getRepository(SomeEntity::class) should always return a repository for the correct manager.

To cut a lot of discussion short: this auto-detection only works when an entity is only managed by a single entity manager. If the same entity is managed by multiple entity managers, getManagerForClass (which is used internally when calling getRepository on the manager registry) will return the first entity manager it discovers that manages the class. In such cases, getRepository on the registry should always be called with a specific entity manager name.

In the future, we may consider throwing an exception in getManagerForClass if we can't find a single entity manager that manages a class. Since this is a BC break, I don't know when we'll be able to add this, but I've created https://github.com/doctrine/persistence/issues/68 to track this.

One more issue that was highlighted here was that of service repositories. Keep in mind that the entire setup of service repositories has the "90%-use-case" in mind, which in this case would be a single entity manager, or at least having the entity only managed by a single entity manager. Once an entity is managed by multiple entity managers, you'd need to have multiple services for the repository, which the system currently doesn't handle. This is not to say that you can't use service repositories at all in such a scenario, you just need to create more glue code to work around these issues. Throwing an exception if an entity is managed by multiple entity managers would also fix this, as the repository service will no longer be instantiable, forcing the user to realise that they've taken a wrong turn somewhere.

So, to summarise:

ipernet commented 5 years ago

Hi @alcaeus

Thanks for your time and the very detailed information given here. I understand the limits of the "service repositories" you describe and so can only agree with the conclusion you draw.

II'll try to contribute to the improvement of the How to Work with multiple Entity Managers and Connections documentation to include the juicy bits of information we have here.

Thanks!

alcaeus commented 5 years ago

Awesome, thanks @ipernet!

ipernet commented 4 years ago

So, to summarise:

* If using multiple entity managers, try not to have an entity managed by multiple managers

* If you do so, always specify the entity manager in question when calling `getRepository` on the registry

* Also, don't use service repositories when managing the same entity with multiple managers. Instead, stick to "classic" repositories or write the glue code yourself.

Hi @alcaeus, as a possible answer to these limitations I have put an idea here: https://github.com/doctrine/DoctrineBundle/issues/1044

Floeig commented 4 years ago

If using multiple entity managers, try not to have an entity managed by multiple managers

The project I have is to build an API to manage 3 db on 3 different sites. So I have to use 1 entity on 3 Managers. I'll wait for the doc Thanks :)

erdincgc commented 4 years ago

After a year still documentation is not enough to cover this issue and still not working in a straight-forward way ... https://github.com/r2my/symfomem this repo is still not working.

Being told : If you do so, always specify the entity manager in question when calling getRepository on the registry is also not working as of 4.3.6

this is not an ignorable problem imho , at least a proper workaround should be added to docs to be prepared for future updates.

ITtoponline commented 4 years ago

Woh, I'm having the same problem with Symfony 4.4. I managed entities that can be present on multiple connections. Doing that does not work at all. I get the error that my table is undefined

$data_niveau = $this->doctrine->getRepository(DataNiveau::class, $connection)->findAll();

Works perfectly fine on SF 3.4. It completely break my application, cannot upgrade to SF 4.4 for now.

gisoftlab commented 4 years ago

This bug is reproduced over and over. Symfony 5.04 still has the same issue.

Glioburd commented 4 years ago

Same problem on a Symfony 3.4 app. The default connection is always used :(

Ph0xEn commented 4 years ago

Hi everyone,

since Symfony 5 the provided workaround from @tech-no-logical (https://github.com/symfony/symfony-docs/issues/9878#issuecomment-472448029) does not longer work.

Has anybody a new solution? I'm struggling at this point.

Thank you very much!

Glioburd commented 4 years ago

Hi everyone,

since Symfony 5 the provided workaround from @tech-no-logical (#9878 (comment)) does not longer work.

Has anybody a new solution? I'm struggling at this point.

Thank you very much!

@Ph0xEn I managed to use a 2nd EM with @soeren-helbig's solution https://github.com/symfony/symfony-docs/issues/9878#issuecomment-523812504. At least it works :).

Ph0xEn commented 4 years ago

Hi @Glioburd,

thank you for the link. It works like a charm :)

ahundiak commented 4 years ago

Very confused. These issues are a result of using the ServiceEntityRepository in order to support autowire. Extend your repository from EntityRepository, exclude your repositories from autowire and (if needed) go back to manually creating and injecting repository services.

13bAdLuCk13 commented 2 years ago

Is the workaround of @soeren-helbig in his comment still working? Could someone give me a more explicit code-example? I can't get his code to run. Or is there already an official solution to use two entity managers for one entity?

ahundiak commented 2 years ago

The DoctrineBundle no official solution to manage one entity type with multiple managers. It has been that way ever since the ServiceEntityRepository class was introduced and seems unlikely to change. Best approach is to simply not do that.

You can however:

  1. Have your repositories inherit from EntityRepository instead of ServiceEntityRepository
  2. Exclude your repositories from autowire
  3. Create a Doctrine\ORM\Repository\DefaultRepositoryFactory service
  4. Change the repository_factory config in doctrine.yaml from ContainerRepositoryFactory to DefaultRepositoryFactory

At this point you should be good to go as long as you are fine with always using $em->getRepository(Entity::class) to get your repositories. If you have the urge to inject the repositories as services then you need to manually define them using a factory service definition. It is what we used to do back in the pre-autowire days.

It is also instructive to compare the DefaultRepositoryFactory with the ContainerRepositoryFactory to see why it's difficult to support multiple entity managers with autowire.

One final note: I have sometime seen stuff about how resetting an entity manager does not work properly with the DoctrineBundle code. I don't do that sort of thing and I don't recall exactly what the problem was. Just be careful if you do happen to use reset.

pouetman87 commented 2 years ago

I use this workaround : https://github.com/symfony/symfony-docs/issues/9878#issuecomment-523812504. I find this to be the simplest solution, And you can still easily use the default repository.

ahundiak commented 2 years ago

@pouetman87 Pretty sure that work around is not doing what you think it is. As long as the ContainerRepositoryFactory is being used then you will never get different repository instances. And swapping around which manager a repository belongs to seems like asking for trouble.

danny-endeavour commented 2 years ago

Found a fix on https://skylar.tech/symfony-doctrine-repository-running-queries-on-wrong-entity-manager/

imbachb commented 1 year ago

Is there a way to add an entity manager in the doctrine config so that it is specifically NEVER used when injecting a repository that extends ServiceEntityRepository? In my case I have an entity manager that should always be used when injecting repositories, but for a special action I want to use a different entity manager that manages the same entities on another database. The only difference between the two entity managers is the database url ... maybe there is an easier way to accomplish this?

Gonzalo1987 commented 1 year ago

What's about using the EntityRepository and load the parameters with:

my.entity.metadata:
    class: App\Entity\Metadata
    arguments: 
        $entityName: App\Entity\MyEntity

App\Repository\MyEntityRepository:
    arguments:
        [$class: my.entity.metadata]

This should solve the problem? A EntityRepository autowireable