Skip to content
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

Rownumber paging generates invalid SQL with DTO projection and orderby #9535

Closed
youclk opened this issue Aug 23, 2017 · 7 comments
Closed

Rownumber paging generates invalid SQL with DTO projection and orderby #9535

youclk opened this issue Aug 23, 2017 · 7 comments
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Milestone

Comments

@youclk
Copy link

youclk commented Aug 23, 2017

I find a bug ,if use RowNumber of paging:

services.AddDbContext<EFDbContext>(
    options => options.UseSqlServer(Configuration.GetConnectionString("XXX"), x => x.UseRowNumberForPaging())
    );

At this point, the orderby fields and select the fields can't be the same:

var test = await _users.OrderBy(i => i.Id)
    .Select(i => new UserInfo
    {
        Id = i.Id
    }).Skip(0).Take(30).ToListAsync();

the translation of sql:

exec sp_executesql N'SELECT [t].[Id]
FROM (
    SELECT [i].[UserID] AS [Id], ROW_NUMBER() OVER(ORDER BY [Id] DESC) AS [__RowNumber__]
    FROM [User] AS [i]
) AS [t]
WHERE ([t].[__RowNumber__] > @__p_0) AND ([t].[__RowNumber__] <= (@__p_0 + @__p_1))',N'@__p_0 int,@__p_1 int',@__p_0=0,@__p_1=30

Error info :the column name 'Id' is invalid

@smitpatel
Copy link
Contributor

We probably need to unwrap AliasExpression.

@smitpatel smitpatel changed the title bug for paging Rownumber paging generates invalid SQL with DTO projection and orderby Aug 25, 2017
@smitpatel smitpatel self-assigned this Aug 25, 2017
@ajcvickers ajcvickers added this to the 2.1.0 milestone Aug 25, 2017
@smitpatel smitpatel added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Aug 28, 2017
smitpatel added a commit that referenced this issue Aug 28, 2017
…owNumberPagingExpressionVisitor

Issue: When converting OFFSET to RowNumber we move order by to projection. OrderBy allows refering to projection by their alias but in projection you cannot refer to another projection by its alias
Solution: We need to unwrap the alias expression in order by when adding to projection so projection expression will print inner expression rather than the alias

Resolves #9535
smitpatel added a commit that referenced this issue Aug 28, 2017
…owNumberPagingExpressionVisitor

Issue: When converting OFFSET to RowNumber we move order by to projection. OrderBy allows refering to projection by their alias but in projection you cannot refer to another projection by its alias
Solution: We need to unwrap the alias expression in order by when adding to projection so projection expression will print inner expression rather than the alias

Resolves #9535
@ajcvickers
Copy link
Contributor

Triage: @smitpatel to document workarounds so we have more information for patch consideration.

@ajcvickers ajcvickers reopened this Dec 19, 2017
@ajcvickers ajcvickers removed this from the 2.1.0 milestone Dec 19, 2017
@smitpatel
Copy link
Contributor

Work-around
For queries like above not using explicit member names for projection avoids the issue.
Like following

var test = await _users.OrderBy(i => i.Id)
    .Select(i => new UserInfo
    {
        i.Id
    }).Skip(0).Take(30).ToListAsync();

If the projection is non-member expression where assigning member name is mandatory, removing skip can help generating correct query but it may cause to fetch large data. Or other option is to do the custom projection on client.

For example,
Queries like following

var test = await _users
    .Select(i => new UserInfo
    {
        DiscountedPrice = i.Price * i.Discount
    })
    .OrderBy(I => i.DiscountedPrice).Skip(0).Take(30).ToList();

// Work-arounds
// Remove skip
var test = await _users
    .Select(i => new UserInfo
    {
        DiscountedPrice = i.Price * i.Discount
    })
    .OrderBy(I => i.DiscountedPrice).Take(30).ToList();

// Remove projection
var test = await _users
    .OrderBy(I => i.Price * i.Discount).Skip(0).Take(30).AsEnumerable()
    .Select(i => new UserInfo
    {
        DiscountedPrice = i.Price * i.Discount
    }).ToList();

@ajcvickers
Copy link
Contributor

Triage: The workarounds and scope of the fix together with feedback are currently not such that this meets the bar for patch.

@smithaitufe
Copy link

Please what is the state of this issue?

I am currently having similar issue. How do I resolve it?

https://aspnetcore.slack.com/archives/C18UW3ALA/p1521474152000171

@ajcvickers
Copy link
Contributor

@smithaitufe This issue is fixed in the 2.1 preview1 release. So the options here are:

  • Use the preview release
  • Use the workarounds listed above
  • Wait for the 2.1 RTM release

@ajcvickers
Copy link
Contributor

@youclk If you are still using RowNumberForPaging, could you please comment on issue #13959 and let us know why?

@ajcvickers ajcvickers removed this from the 2.1.0-preview1 milestone Nov 11, 2019
@ajcvickers ajcvickers added this to the 2.1.0 milestone Nov 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Projects
None yet
Development

No branches or pull requests

4 participants