Open Mike-E-angelo opened 2 years ago
Work-around - Can use sync version.
Blocked on #14551
Issue:
While user is using async API that means we should run query in async way, the queryable operators inside (Count
) is sync version. So when we insert query in place of that Count, it will be in async version returning Task<int>
hence the types don't match. There are 2 ways to avoid
May be we need to throw error using single result operation from sync API inside async compiled query.
Thank you for the investigation @smitpatel. I appreciate you taking the time to look into this.
I hate to ask, but how does the IQueryable
versions manage to work? They are ultimately replacing/running async versions of the synchronous expressions, correct?
Running a sync version of the operation is not a viable workaround, I am afraid. That as well as .Result
will lead to thread starvation and/or deadlock if I understand correctly.
The workaround that I am using the IQueryable
version and calling SingleOrDefaultAsync
on that. I am assuming of course that everything is asynchronous evaluated, and am hoping I am correct in that assumption. :S
The difference is not the operation but rather where the operation occurs. When you are using IQueryable version then you return the enumerable generated by EF Core as return of the compiled query delegate. In this case you are assigning result value to Statistic
member. If you put the Count
operation result as the return of the compiled query delegate that will also work.
If you put the Count operation result as the return of the compiled query delegate that will also work.
I did consider doing this but the reason I am using the projection Statistic
class is I wanted to get 3 counts with one query and store the results in the projection. My understanding is that if the expression has 3 counts, it pulls it as one query and puts the results into the projection class. Whereas if I return just the count as the result value as you are describing, I would need to make 3 separate expressions which each have to be compiled on their own and call the database, resulting in 3 total queries to the database instead of one.
That is my understanding. I would appreciate knowing if I am overlooking and/or misunderstanding something somewhere.
Another possible workaround is to use query batching when it's implemented
Great, thank you for the suggestion @AndriySvyryd. My primary concern is to ensure that I understand everything as designed as it still is challenging to know what is taking place on the (sql) server vs client. What I have been using to gauge the location are the generated SQL scripts that are executed by EFCore via logging. For instance, in the above if there are 3 generated queries/calls then that seems off, and I would see if I can make it one.
It looks like the issue you mention has been open since 2018 which, difficult to believe, is nearly half a decade ago already. š¬ It hasn't even been slated for a milestone if I understand correctly so that does not look like a viable workaround in the short (or even medium) term.
All things considered, I am happy with my current workaround of using the IQueryable
compilation route and calling a Take(1)
/SingleOrDefaultAsync
on it.
Along those lines, I'd like to take this opportunity to thank everyone over there for all your diligent, impressive, and amazing work with this project. Despite these minor challenges, I have been able to query my entire domain model with some pretty involved acrobatics and not have to write any actual SQL to manage/maintain.
For further illustration, my Blazor server-side solution is currently sitting at 106,000 lines of C# code, with zero SQL and only ~100 lines of custom JavaScript. To me, this is living the .NET/C# dream and it's due in part to your project here.
FWIW I have a shout out to the team there in my acknowledgements here: https://alpha.starbeam.one/about/acknowledgements
Thank you again for all your notable efforts and accomplishments. š
@Mike-E-angelo I've yet to use CompileAsyncQuery but to prevent EF Core from running multiple SQL queries to the server I had to put a dummy .Where(x => true)
before .Count()
see this issue: https://github.com/dotnet/efcore/issues/27728
If this is not at all related, feel free to hide this comment.
File a bug
I appear to be running into a bug with
EF.CompileAsyncQuery
when returning an instance object/result vsIQueryable
(which has worked amazingly well).When returning an instance object/result, I run into an
System.ArgumentException
with the simplest of expressions.Include your code
You should be able to load and hit F5 on this solution here: https://github.com/Mike-E-angelo/Stash/blob/master/EfCore.CompiledQueries.BasicExpression/EfCore.CompiledQueries.BasicExpression.sln
Error is encountered here: https://github.com/Mike-E-angelo/Stash/blob/master/EfCore.CompiledQueries.BasicExpression/EfCore.CompiledQueries.BasicExpression/Worker.cs#L34
Include stack traces
Include the full exception message and stack trace for any exception you encounter.
Use triple-tick fences for stack traces. For example:
Include verbose output
NA
Include provider and version information
EF Core version:
6.0.3
Database provider: (e.g. Microsoft.EntityFrameworkCore.SqlServer)Microsoft.EntityFrameworkCore.SqlServer
Target framework: (e.g. .NET 5.0)net6.0
Operating system: Windows 10 IDE: (e.g. Visual Studio 2019 16.3) Visual Studio 2022 17.1 RTM