Skip to content

Conversation

@NetanelPersik
Copy link
Contributor

OrderBy is not fully unique #221

Copy link
Member

@BlaiseD BlaiseD left a 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))
Copy link
Member

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?

Copy link
Contributor Author

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

Copy link
Member

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.

Copy link
Contributor Author

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:
    1. Applying OrderBy even when it was not requested at all.
    2. When one passes some OrderBy we append ThenBy PK as well
  • 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 GetQueryAsync since EF apply the orderBy after 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 Pagination https://google.aip.dev/158

Maybe we can settle for 2. ("When one passes some OrderBy we append ThenBy PK as well")

Copy link
Member

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.

Copy link
Contributor Author

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...

Copy link
Member

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.

Copy link
Contributor Author

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...

Copy link
Member

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) .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks!

@NetanelPersik NetanelPersik force-pushed the master branch 3 times, most recently from 9196508 to 57a9791 Compare December 1, 2024 16:08
@BlaiseD BlaiseD closed this Dec 2, 2024
@BlaiseD BlaiseD reopened this Dec 5, 2024
@NetanelPersik NetanelPersik force-pushed the master branch 2 times, most recently from a92bc96 to 7825141 Compare December 5, 2024 21:15
- Added flag to control this behavior: AlwaysSortByPrimaryKey

OrderBy is not fully unique AutoMapper#221
@BlaiseD BlaiseD merged commit 4cbaa5a into AutoMapper:master Dec 7, 2024
3 checks passed
@BlaiseD
Copy link
Member

BlaiseD commented Dec 7, 2024

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants