I'm using a EF Core DbContext transaction to create/update entities on a SQL Server temporal table.
The data I'm processing (array of items) has a key (Year-Sequential, like: 2023-001
, 2023-002
, etc.) and then a set of attributes that corresponds to other columns on the table below.
One of this attributes identifies the kind of operation: Create
, Update
, Cancel
.
It may happen that I receive a request with many different operations related to a single Year-Sequential key, such as:
2023-001 - Create (<data>)
2023-001 - Update (<data>)
2023-001 - Cancel (<data>)
2023-002 - Create (<data>)
2023-002 - Update (<data>)
2023-002 - Cancel (<data>)
etc.
Since I'm using a temporal table to store this data to be able to track changes on the rows over time, I've coded the processing method like a single DB transaction with inside a recursive method that process subsets of the items. The recursive method works this way:
- It takes the first occurrence of each Year-Sequential key and process it.
- If it finds another time the same Year-Sequential key for another operation, it puts it aside for the next round of processing.
- When all the "not duplicated key" items have been processed, there's a call to
dbContext.SaveChangesAsync()
. - The processed entities are created and have the
EntityId
value assigned by the database (that I need to use for the next steps of processing). - If the list of "duplicated key items" is not empty, the method recursively calls itself on the duplicates list and starts again from step 1. If instead, the duplicated key items list is empty, the method ends and then there's a call to
transaction.CommitAsync()
, to commit the transaction and save everything to the database.
Everything works, but there's a problem with Start/End date used for temporal table period.
For each round of the recursive method I correctly get a row created on each single Year-Sequential key. So, taking previous data example, on the History table I've 2 old rows about 2023-001
(Create, 1st Update) with the same EntityId
and, on the Current table, I've the third (2nd Update) row, so the one related to the last 2023-001 Cancel
operation.
See the queries screenshot below.
The problem is that if I make a temporal query on that data ([MovimentiDati]
table), using the FOR SYSTEM_TIME ALL
clause, I get back only the current row! No way I can get the old rows too, but they exists! So, the history is all there but I can't get it!
Instead, if I query the History table ([MovimentiDatiHistory]
) I correctly see the old rows with the same EntityId
.
On the screenshot, you see 5 items with the same issue. For example, take the row with MovimentoId = 399
, you can see:
- on
MovimentiDatiHistory
table: Creation of the row (1st run of recursive method and 1st call todbcontext.SaveChangesAsync()
) - on
MovimentiDatiHistory
table: First update on the row (2nd run of recursive method and 2nd call todbcontext.SaveChangesAsync()
) - on
MovimentiDati
(current) table: Second (and last) update on the row (3rd run of recursive method and 3rd call todbcontext.SaveChangesAsync()
)
But, as highlighted in red, you can also see that Start/End date timestamps are identical! And I think this is the reason why I cannot get the correct result when I query the data from [MovimentiDati]
table (current) with the temporal clause.
I'm not sure about where the problem is, if in the EF Core library or in SQL Server, but I would like to elaborate on the matter...