Sam
Sam

Reputation: 14586

paging using the breezejs web api controller

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

Answers (1)

RaghuRam Nadiminti
RaghuRam Nadiminti

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

Related Questions