Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with multiple entity managers #921

Closed
fabienlem opened this issue Feb 18, 2019 · 7 comments
Closed

Issue with multiple entity managers #921

fabienlem opened this issue Feb 18, 2019 · 7 comments

Comments

@fabienlem
Copy link

Bug Report

With multiple entity managers dealing with same entities, repository objects always use the default entity manager.

Q A
BC Break looks like
Version 2.5.14

Summary

I have two entity managers in order to synchronise two databases that share the same schema.

Let's say I have the following managers: $entityManager1 and $entityManager2.

When my repository class extends Doctrine\ORM\EntityRepository: $entityManager1->findAll() and $entityManager2->findAll() work as expected.

But when my repository class extends Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository, both $entityManager1->findAll() and $entityManager2->findAll() perform query on the $entityManager1 managed database.

I need to extend Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository in order to allow services injection:

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

Do you have any hints to solve this issue?

Thank you.

@Majkl578 Majkl578 transferred this issue from doctrine/orm Feb 18, 2019
@SenseException
Copy link
Member

This issue was transferred from Doctrine ORM with an unsupported 2.5 version Can you please try to recreate this behaviour with the newest DoctrineBundle and a current ORM version?

@alcaeus
Copy link
Member

alcaeus commented Feb 19, 2019

But when my repository class extends Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository, both $entityManager1->findAll() and $entityManager2->findAll() perform query on the $entityManager1 managed database.

Important information to begin with: your entity should only be registered with one entity manager, not multiple ones. The ServiceEntityRepository queries the ManagerRegistry for the correct manager for a given entity:

$manager = $registry->getManagerForClass($entityClass);

So, if your entity class is registered with multiple entity managers, the repository will always use the first entity manager that matches. I don't know your use-case, but I don't see a reason why you should have multiple entity managers in charge of the same entity class, that just leads to problems eventually.

Note that you don't have to extend ServiceEntityRepository directly, you may also extend from EntityRepository and implement the ServiceEntityRepositoryInterface: the interface is what controls auto wiring and auto registration in the Symfony container; the class itself is just a convenient way to write as little code as possible. If you want to be in charge of entity manager selection in your repository, don't extend ServiceEntityRepository but add your own logic.

@fabienlem
Copy link
Author

Hello @alcaeus,

Thank you a lot for your reply!

My use case is the following: I synchronize two versions of the same database. Each version is managed by its own entity manager.

Do you have any suggestion regarding how to achive this "the right way"?

Thank you again!

Fabien

@alcaeus
Copy link
Member

alcaeus commented Feb 19, 2019

Do you have any suggestion regarding how to achive this "the right way"?

Don't extend ServiceEntityRepository but only implement the interface. In the constructor you'll have to call the parent constructor passing in the entity manager of your choice. In your case, instead of fetching the first entity manager that manages your class you should select one by name (e.g. $registry->getManager('myManager');.

@fabienlem
Copy link
Author

fabienlem commented Feb 19, 2019

@alcaeus sorry I don't understand.

If I do that, that means the repository is dedicated to only one of my two entity managers. I want it to be usable for both.

I do such things:

$localEntity = $localEntityManager->getRepository(Example::class)->findOnById(1);
$remoteEntity = $remoteEntityManager->getRepository(Example::class)->findOnById(1);
compare($localEntity, $remoteEntity);

Fabien

@alcaeus
Copy link
Member

alcaeus commented Feb 19, 2019

You'll need to:

  • manually create two services for your repository
  • manually select which entity manager each repository receives

Automatically creating a service for this repository (via a service prototype) won't work as that will only create a single repository which will only be registered in the repository factory for one entity manager.

@fabienlem
Copy link
Author

Ok that's bad news as it involves a signifiant refactoring effort.

Thank you again for your help! Kind regards!

@alcaeus alcaeus closed this as completed Feb 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants