Aloha,
Not sure who is aware of this, but I learned this the hard way yesterday:
If a transaction fails with Doctrine2, you might as well output a static page
and die, because you cannot rely on anything that uses Doctrine2 ORM to still
work and with all the possible listeners etc you are pretty much screwed.
Doctrine2 EntityManager doesnt offer any method to get the EntityManager back
into a working state, mainly because there are potentially references from
proxies that would then point to a bogus EntityManager if the UoW would just be
cleared. I do not know all the details, but Benjamin is pretty convinced its
impossible to be able to fix an existing EntityManager instance.
First up of course one should always try and prevent failed transactions.
However its not always possible to do so without adding elaborate locking
mechanisms to prevent any sort of race condition. Also in some cases it might
just be too much overhead to try and verify everything (think importing a large
XML file).
So when a transaction does fail the only solution is to effectively make a
totally new EntityManager according to Benjamin.
Now if you use Container injecting this is less of a problem (though still
problem, more below). If you don't, you basically need to not only make the new
instance, but you also need to magically find out all the places that follow
the failed transaction (DB logger, rendered form with DB filled choice fields.
Now if you do inject the Container everywhere and never assign it to a class
property all you have to do is reset the service. However this is less trivial
than you might think because of service aliasing:
// reset the EM and all aias
$container->set('doctrine.orm.entity_manager', null);
$container->set('doctrine.orm.default_entity_manager', null);
// get a fresh EM
$em = $this->container->get('doctrine.orm.entity_manager');
Now I am not sure if there is a method that would help me introspect the
alias's, or if we need a magic method to be able to reset all aliases.
Another approach could be of course to simply always clone the EM before
starting any transaction, but that doesnt seem all too feasible.
Another approach could be to simply always use a wrapper around the
EntityManager that gets the Container injected and provides a reset() method.
Thoughts, ideas, prayers? :)
regards,
Lukas Kahwe Smith
[email protected]
--
If you want to report a vulnerability issue on symfony, please send it to
security at symfony-project.com
You received this message because you are subscribed to the Google
Groups "symfony developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/symfony-devs?hl=en