DoctrineMigrationsBundle icon indicating copy to clipboard operation
DoctrineMigrationsBundle copied to clipboard

Multiple entity managers support

Open dinamic opened this issue 12 years ago • 61 comments

Inside our ERP system we have calls to multiple database storages. To use them with Symfony2, we've defined them as different connections each one attached to a different entity manager.

If we make some change to the database structure there is no way to specify on which entity manager this change is going to be performed.

This can be controlled via the command line, but doing so is not reliable, unless we cherry-pick the doctrine migrations on deployment and specify different "--em" argument depending on the current migration.

dinamic avatar Jul 04 '12 12:07 dinamic

+1

richsage avatar Feb 26 '13 16:02 richsage

+1

zodeus avatar Mar 01 '13 00:03 zodeus

+1

hasumedic avatar Mar 06 '13 11:03 hasumedic

Awesome!

suncat2000 avatar Mar 12 '13 19:03 suncat2000

+1

hason avatar Apr 18 '13 08:04 hason

+1

aclarkd avatar Jun 13 '13 18:06 aclarkd

Currently this can be achieved by using Container Aware Migrations. If one can have the service container injected, he can obtain an instance of some entity manager and its connection.

Here's a reference.

By the time of posting this issue there was no such functionality. It is, however, considered as a workaround. It does not seem right to have the container on your disposal.

dinamic avatar Jun 14 '13 09:06 dinamic

+1

odino avatar Jul 08 '13 12:07 odino

Another workaround would be to implement the --configuration option properly. Currently the $this->configuration (AbstractCommand) gets overwritten with the default and therefore does not do what it was supposed to do: run migrations from a specific folder, using a specific migrations table. Changing the if statement in getMigrationConfiguration (if (! $this->configuration) to always pass (true || ! $this... ) allowed me to use a different folder, a different table and (in combination with --em) a different entity manager.

EDIT: just saw there is a fix... https://github.com/doctrine/DoctrineMigrationsBundle/issues/18

newneon avatar Jul 30 '13 14:07 newneon

:+1:

But seriously: What happened to this ticket?

kingcrunch avatar Jan 14 '14 22:01 kingcrunch

Two years later nothing has changed.

I am still going to recommend the Container Aware Migrations as a workaround.

dinamic avatar Jul 17 '14 10:07 dinamic

:thumbsup: +1 Hope to see this someday...

Max101 avatar Aug 06 '14 14:08 Max101

For me, ContainerAwareInterface approach is completely sufficient and working. I suggest closing, since 2 years passed with no PR.

TomasVotruba avatar Aug 15 '14 16:08 TomasVotruba

@dinamic how do you use the new entity manager to execute the migrations? From the container you can get the proper $em but then, the addSql() calls continue using the other connection.

class Version20141028122535 extends AbstractMigration implements ContainerAwareInterface
{
    private $container;

    /**
     * @var EntityManager
     */
    private $em;

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    public function preUp(Schema $schema)
    {
        $this->em = $this->container->get('doctrine.orm.shared_entity_manager');
    }

    public function preDown(Schema $schema)
    {
        $this->em = $this->container->get('doctrine.orm.shared_entity_manager');
    }

    public function up(Schema $schema)
    {
        // this up() migration is auto-generated, please modify it to your needs
        $this->abortIf($this->em->getConnection()->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('CREATE TABLE new_table (id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
    }

    public function down(Schema $schema)
    {
        // this down() migration is auto-generated, please modify it to your needs
        $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('DROP TABLE new_table');
    }
}

arnaugm avatar Oct 28 '14 12:10 arnaugm

Yea, that was a problem I noticed when I tried it later on. I ended up getting the connection from the entity manager and executing the queries towards it. It's not ideal, but it works and we don't really have another way around.

dinamic avatar Nov 04 '14 19:11 dinamic

ContainerAwareInterface has nothing to do with this issue. With ContainerAwareInterface you can get any entity manager you want, but you don't know what entity manager was selected in command line.

raistlin avatar Dec 05 '14 10:12 raistlin

That's correct. You don't know and you don't actually care what's selected on the command line.

The ContainerAwareInterface solves a problem here, it's not the cause of it.

We are still waiting for a proper fix to be applied for this problem. Until then, ContainerAwareInterface is the necessary evil.

dinamic avatar Dec 05 '14 22:12 dinamic

+1

ryall avatar Jan 28 '15 20:01 ryall

+1

pasmaill avatar Mar 11 '15 19:03 pasmaill

+1

eggyal avatar May 21 '15 16:05 eggyal

A few downsides I found to the proposed container workaround:

  • It's ugly as hell.
  • You get a console warning for not executing any SQL.
  • The queries get executed even if you do a dry-run.

sp-enric-fradera avatar Jul 27 '15 15:07 sp-enric-fradera

@stof We have a fork where we added support for this. Kinda necessary with 16 EMs on the app.

Couple of things:

  • we need to track the em migration was executed against like so http://i.imgur.com/aAhHfuh.png
  • changes to doctrine/migrations are necessary

If we clean the code up a bit would you be in a position to merge a PR in on both this repo and doctrine/migrations ?

spinx avatar Aug 13 '15 13:08 spinx

@spinx does it really need a change in doctrine/migrations itself ? what kind of change ?

stof avatar Aug 17 '15 18:08 stof

@stof Mostly changes to commands. To allow diffing on all EMs, generating migrations for EMs. As I mentioned the only downside is that you need to track which EM the migration is for so you need to append EM name or similar to the migration version.

spinx avatar Aug 17 '15 18:08 spinx

@spinx or you just use different configuration for different em and your problem is already solved.

mikeSimonson avatar Aug 17 '15 21:08 mikeSimonson

@mikeSimonson I'm not sure I understand what you mean by that. Can you elaborate ?

spinx avatar Aug 18 '15 12:08 spinx

@spinx For each migration command you can pass an entity manager and a migration configuration. In the migration configuration you can set the migration folder and the sql table that will hold the version migrated. Then you create an em configuration for all your different em.

The result will be that the migration on your different em are going to be independent of each other.

mikeSimonson avatar Aug 18 '15 14:08 mikeSimonson

Ah, I see. Might be a way to go, not sure.

@stof Is adding em to migration version acceptable ? Or maybe a column of 'manager' that defaults to 'default' instead, to have more backwards compatibility. People are probably relying on versions to be integers, right?

spinx avatar Aug 18 '15 15:08 spinx

That would be a huge BC break and honestly you shouldn't use the em for migrations in the first place. It's only going to bring you performance issues and troubles.

mikeSimonson avatar Aug 18 '15 15:08 mikeSimonson

Wouldn't use the EM but you somehow need to know against which EM you want to execute. Also if you are diffing to generate migrations files, the way it works now, having unix time as version, you can't really generate migrations for multiple EMs. Well you can do sleep(1) which is a bas solution as well.

spinx avatar Aug 18 '15 15:08 spinx