-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Flush could delete entities before inserting new ones #5742
Comments
I'm not quite sure if |
+1 here |
+1 That is quite a challenge to respect OCP when doctrine removes "merge". There is no way to update an object from a clone within a transaction. How to have a separation of concerns between logic and persistance when we must flush a state in the middle of logic |
I faced this issue as well on my client project. We had to remove the SQL unique constraint on the table to ensure the Doctrine SQL transaction can be complete. But ideally we would need both the SQL unique constraint (to always ensure consistency in the database) and in the SQL transaction when Doctrine flush statement is performed. |
@SmasherHell I am not sure if it would support your use case – probably it may be difficult to deal with two entities at the same time that share the same primary key value, and to have one replace the other in a single transaction. The OP request is more about being able to meet other (non-primary key) constraints. |
There are a few requests (doctrine#5742, doctrine#5368, doctrine#5109, doctrine#6776) that ask to change the order of operations in the UnitOfWork to perform "deletes before inserts", or where such a switch appears to solve a reported problem. I don't want to say that this is not doable. But this PR at least adds two tricky examples where INSERTs need to be done before an UPDATE can refer to new database rows; and where the UPDATE needs to happen to release foreign key references to other entities before those can be DELETEd. So, at least as long as all operations of a certain type are to be executed in blocks, this example allows no other order of operations than the current one.
#10809 adds an example that shows why we cannot – at least not, in general – change the current order of operations in the UoW. |
There are a few requests (doctrine#5742, doctrine#5368, doctrine#5109, doctrine#6776) that ask to change the order of operations in the UnitOfWork to perform "deletes before inserts", or where such a switch appears to solve a reported problem. I don't want to say that this is not doable. But this PR at least adds two tricky examples where INSERTs need to be done before an UPDATE can refer to new database rows; and where the UPDATE needs to happen to release foreign key references to other entities before those can be DELETEd. So, at least as long as all operations of a certain type are to be executed in blocks, this example allows no other order of operations than the current one.
may I ask why the order is not simply preserved? that would likely be the expectation of the library user. doctrine reordering actions is susprising. |
No, that’s the promise given by the ORM: You tell it which entities you want to have tracked, and when you call That includes giving the ORM some freedom to order operations as it sees fit. Additional unique constraints in the database as we‘re discussing here may interfere with that. They prevent the ORM from doing things in the planned order, through restrictions it cannot foresee and/or efficiently include in the commit order computation. |
can you give an example where not keeping the order is neccessary to fulfil that promise? |
hmm, but i don't quite see how this completely prevents keeping ordering. yes in some situations things need to be reordered, but if one really only does the required reorderings and keeps things otherwise stable I think most of the problems would go away, or am I overlookling something? |
I think that is how it is implemented. If you have a reproducible case that indicates otherwise, I’d be happy to look into it as a potential bug |
Ah ok, well need to find out how to reduce this. But basically i am removing an entity and then adding another one with the same primary id. Adding a flush between makes it work. Hmm, but maybe we are using a too old doctrine version. Will check |
You’re even describing a special case where the unique constraint is for the primary key, not just for any other column. You must be using application-provided IDs, otherwise this kind of ID reuse would not happen. This is not going to work for at least one reason apart from the order of operations during flush: Since the identity map refers to entities (object instances) by means of the ID, there will be a collision already when you try to add the one object and have the other one set up for removal. |
Is there then a stable way to completely replace an object? |
I have a unique (not PK) column. I need to remove old entities first and then add new ones (replacements).
Yeah, I've seen this: #5368
But I've also seen a "could be done" solution:
What I propose, is that this gets implemented. From the dev point of view, it would be cool, if one could do that like this:
* @ORM\OneToMany(targetEntity="Whatever", mappedBy="Me", cascade={"persist"}, orphanRemoval=true, removeBeforeAdd=true)
The text was updated successfully, but these errors were encountered: