When making changes to DbSet<>
(like Add
/Remove
) what would be the order in which 'insert'/'delete' operations will be performed during SaveChanges
?
Currently I'm observing 'deletes' before 'inserts' and that's what I would expect but couldn't find any official docs about it.
The problem I'm trying to prevent is that entities in question are controlled using unique constraint. And so I need to 'delete' old and 'insert' new ones. Doesn't matter in which order the 'inserts' would happen. What matters is the order of 'deletes' before 'inserts'.
Is this order described and fixed or we are forced to make SaveChanges
in-between?
UPDATE_01:
Some more details.
Here is a sample minimized table schema:
CREATE TABLE "ClientContracts" (
"Id" int4 NOT NULL GENERATED ALWAYS AS IDENTITY,
"ClientId" int4 NOT NULL,
"Code" text NOT NULL,
"IsEnabled" bool NOT NULL,
CONSTRAINT "PK_ClientContracts" PRIMARY KEY ("Id")
);
CREATE UNIQUE INDEX "IX_ClientContracts_ClientId_IsEnabled" ON public."ClientContracts" USING btree ("ClientId", "IsEnabled") WHERE "IsEnabled";
CREATE UNIQUE INDEX "IX_ClientContracts_Code" ON public."ClientContracts" USING btree ("Code");
A client (ClientId
) can have multiple contracts assigned to it. But only one of them is active in a given moment (IsEnabled
) controlled with a IX_ClientContracts_ClientId_IsEnabled
constraint. Also each contract's Code
is unique and controlled with a IX_ClientContracts_Code
constraint. There are cases when a contract could be deleted by a client and added again with the same Code
. And sometimes it could an active one.
In order to fulfill both constraints I see 2 ways:
- first delete the needed contracts (the list of contracts is supplied by an external service),
SaveChanges
, insert new ones andSaveChanges
again. This way we can be sure that constraints won't be 'triggered' since we have securely deleted previous entries before adding those that are in conflict. DbSet<ClientContracts>
.Add
/Remove
thenSaveChanges
and make EF handle deletes before inserts.
Multiple users and simultaneous changes are not accounted here. Single user at a time. Also an external service tries it's best to make sure that multiple contracts with the same code are not sent for processing (constraints are the 'last line of defense here').
So the main question is either we take the route (1)
or (2)
.
Of course the most safest is (1)
since we control the flow in this case. But this results in more code and more batches/connections.
So perhaps could it be safe to go for (2)
?
And again. We are not talking about order of inserts or deletes themselves (i.e. doesn't matter if entity_1
is deleted after entity_3
or entity_5
is inserted before entity_1
). Just about that deletes comes before inserts.