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

Re-introduce detection for non-composable SQL in FromSql #17558

Closed
Julien-Marpault opened this issue Sep 2, 2019 · 13 comments · Fixed by #18323
Closed

Re-introduce detection for non-composable SQL in FromSql #17558

Julien-Marpault opened this issue Sep 2, 2019 · 13 comments · Fixed by #18323
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-enhancement
Milestone

Comments

@Julien-Marpault
Copy link

.Net core 3 preview 8

  HomeCarouselViewModel viewModel = await _context.Set<HomeCarouselViewModel>().FromSqlRaw("EXEC GetHomeCarousel").AsNoTracking().FirstOrDefaultAsync(); 

I get this exception:
Incorrect syntax near the keyword 'EXEC'

Worked perfectly with ef core 2.2

@ErikEJ
Copy link
Contributor

ErikEJ commented Sep 2, 2019

Maybe need to use dbo.GetHomeCarousel

@Julien-Marpault
Copy link
Author

No it doesn't change anything.

Thanks.

@ajcvickers ajcvickers changed the title Stored Procedure exception Re-introduce detection for non-composable SQL in FromSql Sep 7, 2019
@ajcvickers
Copy link
Contributor

Notes from triage: The code to detect non-composable SQL was removed in 3.0, since ideally we would not parse any SQL. However, if this catches enough people out, then we will consider re-introducing it. Putting this in backlog to gather votes/feedback.

@ajcvickers ajcvickers added this to the Backlog milestone Sep 7, 2019
@Julien-Marpault
Copy link
Author

Thanks,
Since you do that, how to use stored procedure through EF ?

@ajcvickers
Copy link
Contributor

Re-marking for triage. What is the composition here? I assume it's FirstOrDefault? But then I'm left thinking that FirstOrDefault is not an unreasonable thing to "client-eval" here, since it means take the first result from the reader, if there is one, and return it.

@ajcvickers ajcvickers removed this from the Backlog milestone Sep 8, 2019
@divega divega added this to the Backlog milestone Sep 9, 2019
@ethos-tim
Copy link

ethos-tim commented Sep 24, 2019

I am porting and running into this with FirstOrDefault AND Select on a FromSqlRaw and FromSqlInterpolated it is trying to add a SELECT TOP(1) or change the column list ON TOP of my stored procedure. Adding an AsEnumerable or ToList before the FirstOrDefault or Select fixes the issue - however it was very frustrating to find and I had to run SQL Profiler to figure it out. The error it was throwing was Incorrect syntax near '@p0'. Perhaps have a flag that allows the user to indicate "Don't mess with my SQL - just run it as is". I can create a repo if needed.

@ethos-tim
Copy link

ethos-tim commented Sep 24, 2019

Thanks,
Since you do that, how to use stored procedure through EF ?

Try:

HomeCarouselViewModel viewModel = await _context.Set<HomeCarouselViewModel>()
.FromSqlRaw("EXEC GetHomeCarousel")
.AsNoTracking()
.AsEnumerable()
.FirstOrDefaultAsync(); 

@smitpatel
Copy link
Contributor

"Don't mess with my SQL - just run it as is".

There is very easy way to do this.
_context.Set<T>().FromSqlRaw(.....).AsEnumerable()
Put AsEnumerable right after FromSqlRaw and EF will not try to do any composition.

@Julien-Marpault
Copy link
Author

Thanks.
In effect it works:

 HomeCarouselViewModel viewModel =  _context.HomeCarouselViewModel.FromSqlRaw("EXECUTE GetHomeCarousel").AsNoTracking().AsEnumerable().FirstOrDefault();

But it's synchronous. In order to use Asynchronous operation I Thought I could use AsEnumerableAsync() but

    HomeCarouselViewModel viewModel = _context.HomeCarouselViewModel.FromSqlRaw("EXECUTE GetHomeCarousel").AsNoTracking().AsAsyncEnumerable().GetAsyncEnumerator().Current;

returns null.

@ErikEJ
Copy link
Contributor

ErikEJ commented Sep 25, 2019

Did you forget await ?

@smitpatel
Copy link
Contributor

Step-by-step

  • AsAsyncEnumerable() gives you IAsyncEnumerable<>, an async enumerable
  • GetAsyncEnumerator() gives you IAsyncEnumerator<>, an async enumerator over previous enumerable
  • Calling into Current will give you current element in enumerator but before you call into Current you need to call MoveNextAsync.

You have initialized your enumerator but haven't moved it yet so Current is null (or default value).

@smitpatel smitpatel removed this from the Backlog milestone Oct 7, 2019
@ajcvickers ajcvickers added this to the 3.1.0 milestone Oct 10, 2019
@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 Oct 10, 2019
smitpatel added a commit that referenced this issue Oct 16, 2019
Also fix issues tags
- Tags are erased when SelectExpression is recreated during visitation
- Tags are not printed for non-composed FromSql*

Resolves #17558
smitpatel added a commit that referenced this issue Oct 16, 2019
Also fix issues tags
- Tags are erased when SelectExpression is recreated during visitation
- Tags are not printed for non-composed FromSql*

Resolves #17558
smitpatel added a commit that referenced this issue Oct 16, 2019
Also fix issues tags
- Tags are erased when SelectExpression is recreated during visitation
- Tags are not printed for non-composed FromSql*

Resolves #17558
smitpatel added a commit that referenced this issue Oct 17, 2019
Also fix issues tags
- Tags are erased when SelectExpression is recreated during visitation
- Tags are not printed for non-composed FromSql*

Resolves #17558
@ajcvickers ajcvickers modified the milestones: 3.1.0, 3.1.0-preview2 Oct 24, 2019
@ajcvickers ajcvickers modified the milestones: 3.1.0-preview2, 3.1.0 Dec 2, 2019
@thassan1977
Copy link

this worked for me just fine

string sqlQuery = "EXEC [dbo].[PaperBatch_INSERT] @UserName,@SupplierID,@OrDerno,@RecvDat,@FROMno,@tono,@notes";

resp = this.SPResponse.FromSqlRaw(sqlQuery,
p_UserName, p_SupplierID,
p_OrderNo, p_RecvDat,
p_FromNo, p_ToNo, p_Notes)
.AsNoTracking().AsEnumerable().FirstOrDefault();

@lixaotec
Copy link

Re-marking for triage. What is the composition here? I assume it's FirstOrDefault? But then I'm left thinking that FirstOrDefault is not an unreasonable thing to "client-eval" here, since it means take the first result from the reader, if there is one, and return it.

It should works like that. It seem so odd to workaround with AsEnumarable.

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. customer-reported type-enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants