-
Notifications
You must be signed in to change notification settings - Fork 57
Make orderBy unique for paging. #222
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
Conversation
BlaiseD
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pre-existing unrelated logic should not change. Neither should any of the existing tests.
| /// <returns></returns> | ||
| public static Expression<Func<IQueryable<T>, IQueryable<T>>> GetQueryableExpression<T>(this ODataQueryOptions<T> options, ODataSettings oDataSettings = null) | ||
| { | ||
| if (NoQueryableMethod(options, oDataSettings)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic did not create the OrderBy if there were no related methods Top, Skip etc... Why did that have to go?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we don't want to return null on NoQueryableMethod we always need to append some orderBy: #221
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't agree. Microsoft.AspNetCore.OData.Query.EnableQueryAttribute does not sort by default either which leads me think that the logic enforcing the "ThenBy PK" sort really belongs in your own code. We should close this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before closing this, just want to point out few things:
- Please notice there are 2 parts here:
- Applying
OrderByeven when it was not requested at all. - When one passes some
OrderBywe appendThenByPK as well
- Applying
- Saying that "Microsoft doesn't do it so we shouldn't do it" isn't really a valid argument...
- It is difficult to do it after
GetQueryAsyncsince EF apply theorderByafter the LIMIT which ruins the point:
SELECT *
FROM (
SELECT *
FROM "Cases" AS "c"
ORDER BY "c"."Type" DESC
LIMIT @__p_0
) AS "t"
ORDER BY "t"."Id"
- This is a general//real issue during paging, solving this can help us make paging consistent, it can also opens us to
Keyset Paginationhttps://google.aip.dev/158
Maybe we can settle for 2. ("When one passes some OrderBy we append ThenBy PK as well")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the other way round. Changing the code needs justification - leaving it untouched doesn't.
Adding the ThenBy to your request when necessary is better. Then it does not have to run for users who are not requesting it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is to add thenBy pk to requests containing $orderBy=notPk
So if the request looks like this:
"/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$orderby=Name desc"
We want it to look like this:
"/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$orderby=Name desc,Identity";
Notice we chained Identity to the orderBy to make it unique in case orderBy=Name will return duplicates (since Name is not unique)
That way paging will be consistent...
Databases will return random order for duplicate values...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct - just do this: "/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$orderby=Name desc,Identity"; Otherwise we'd be adding the ThenBy for every user on every request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO adding thenBy pk on every request is best practice.
I don't want the consistency of my paging depending on customers (whether they pass Identity or not) also notice I don't change the request itself, it is immutable, internally im taking care of adding thenBy...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should work if we add an opt-in flag to ODataSettings. Something like ODataSettings.AlwaysSortByPrimaryKey then we can do both behaviors when that flag is set (PK sort when NoQueryableMethod plus the ThenBy PK) .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks!
9196508 to
57a9791
Compare
a92bc96 to
7825141
Compare
- Added flag to control this behavior: AlwaysSortByPrimaryKey OrderBy is not fully unique AutoMapper#221
|
Thanks |
OrderBy is not fully unique #221