Reputation: 14586
I've implemented paging in the great CodeCamper SPA by John Papa. While doing so, I have found something strange when using the take() and skip() functions.
Consider the following ODATA query for skipping 2 records and take 2:
/api/Breeze/Sessions?$orderby=TimeSlotId%2CLevel%2CSpeaker%2FFirstName&$skip=2&$top=2&$select=Id&$inlinecount=allpages
This returns:
[{"$id":"1","$type":"IB_pMnaszsw5zIeP0Q7Dam12XmjGGg[[System.Int32, mscorlib]], IB_pMnaszsw5zIeP0Q7Dam12XmjGGg_IdeaBlade","Id":3},{"$id":"2","$type":"IB_pMnaszsw5zIeP0Q7Dam12XmjGGg[[System.Int32, mscorlib]], IB_pMnaszsw5zIeP0Q7Dam12XmjGGg_IdeaBlade","Id":14}]
Now I skip 4 records and take 2 (as if moving to the next page)
/api/Breeze/Sessions?$orderby=TimeSlotId%2CLevel%2CSpeaker%2FFirstName&$skip=4&$top=2&$select=Id&$inlinecount=allpages
This returns:
[{"$id":"1","$type":"IB_pMnaszsw5zIeP0Q7Dam12XmjGGg[[System.Int32, mscorlib]], IB_pMnaszsw5zIeP0Q7Dam12XmjGGg_IdeaBlade","Id":14},{"$id":"2","$type":"IB_pMnaszsw5zIeP0Q7Dam12XmjGGg[[System.Int32, mscorlib]], IB_pMnaszsw5zIeP0Q7Dam12XmjGGg_IdeaBlade","Id":11}]
I am getting the record with Id 14 twice ! I can reproduce this issue with any number of pages or records.
Any idea what's going on ?
[EDIT]
Ok, I've noticed that if get rid of the orderby ($orderby=TimeSlotId%2CLevel%2CSpeaker%2FFirstName&) then everything's fine. How come the orderby is causing a problem ?
Upvotes: 1
Views: 353
Reputation: 6793
To make paging work, there should be a stable sort. We do that with the [QueryableAttribute]
by trying to figure out what the keys are and adding them to the order by clause if they are not already present in the query. Now, inferring the key of the entity is on a best effort basis based on a few set of conventions like if the entity has a property with name Id or if the entity has a property with [KeyAttribute]
etc.
I suspect that we were not able to figure out the key properties of Session
for your IQueryable<Session>
. So, there is no stable sorting order enforced. Now the reason it might work without the $orderby is that the table itself might be ordered. Again, I am guessing that you are not using entityframework as entityframework would throw if there is a Skip
or Take
without a stable sorting orderby
.
Now, the way to fix this (assuming my earlier guesses are right :)) is to ensure a stable ordering yourself and tell the QueryableAttribute to stop trying to do a stable sort by setting EnsureStableOrdering
to false
.
Upvotes: 0