-
Notifications
You must be signed in to change notification settings - Fork 474
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
Async query serialization #2152
Comments
@tomasfabian If I understand your question correct, You should just return an object, which implements IAsyncEnumerable. You may read it here: https://docs.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-3.1#return-ienumerablet-or-iasyncenumerablet This addresses, what you ask for:
|
Hi @tomasfabian, please let us know if the solution proposed by @henrikdahl8240 works for you. |
Hi @henrikdahl8240, yes you understand my question correctly. I'm using AspNetCore 3 OData 7.4 with Entity Framework 6.4. I'm afraid, that I'm probably not able to return IAsyncEnumerable, because OData queries are composable: However I tried to take control of the query composition in this way: //[EnableQuery]
public async IAsyncEnumerable<object> Get(ODataQueryOptions<TEntity> queryOptions, [EnumeratorCancellation]CancellationToken cancellationToken)
{
ValidateQuery(queryOptions);
IQueryable<TEntity> queryable = repository.GetAll();
var dbAsyncEnumerable = ((IDbAsyncEnumerable)queryOptions.ApplyTo(queryable));
using (var enumerator = dbAsyncEnumerable.GetAsyncEnumerator())
{
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return enumerator.Current;
}
}
} But the client side dataServiceContext throws System.InvalidOperationException: The response payload is a not a valid response payload. var test = await ((DataServiceQuery<Order>) dataServiceContext.Orders.Take(1)).ExecuteAsync(); I think that it is caused by missing metadata. Thank you very much, Tomas |
You didn't write, that you use Entity Framework 6.4. I assumed you use Entity Framework Core >= 3.0 due to the nature of your question. For EF Core the problem is solved using e.g. EntityFrameworkQueryableExtensions.AsAsyncEnumerable(IQueryable) Method as documented here: https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.entityframeworkqueryableextensions.asasyncenumerable?view=efcore-3.1. I think the issue is, that Entity Framework 6.4 is not a good citizen when it comes to .NET 3.0 which introduced IAsyncEnumerable. EF 6.4 just supports .NET Core "to survive" so to speak. EF 6.4 does not support IAsyncEnumerable for instance because .NET Framework does not support IAsyncEnumerable. Basically I think, that your situation boils down to either it will never come to work with EF 6.4 or you can change for EF Core, which is a good citizen when it comes to .NET 3.0 and therefore supports IAsyncEnumerable first class using the method I referred to. Actually I don't think, that what you refer to as "composable" is what is called composable when it comes to OData, i.e. to just use some basic OData features like filter and select. OData supports composability when it comes to functions. You explicitly ´mark a function in the builder to be composable if you have such a wish. |
I didn't mention EF 6.4, because I mentioned IQueryable, but in this case IQueryProvider is more important as I understand it. I found out that EF Core extends this interface with IAsyncQueryProvider. In my opinion EF 6.4 could support IAsyncEnumerable for NETCOREAPP3.1 by using conditional compilation. I understand that NETFRAMEWORK is out of the question, because it does not support NETSTANDARD2.1 where IAsyncEnumerable was introduced. @habbes it seems that other ORM's like NHibernate have the same issue: @henrikdahl8240 long story short regarding to the .Net Core "good citizen". I have created a lot of services in .Net Framework with Entity Framework during the last decade. Nowadays I'm migrating them to .Net Core and Microsoft made a GREAT decision and ported EF6 to .Net Core. It would be very time consuming for us to test hundreds of WPF and other client apps relying on these web services (successfully migrated to .NET Core). WCF is another story... I'm ready to switch to EF Core when it will be ready, too. But it lacks features like many-to-many without CLR class for join table. It has 1384 opened issues at the time of writing. It would be too risky to move to EF Core at this moment, and it will be a lot of work for developers, testers etc. We and other teams in the world can achieve this transition only step-by-step. I'm aware about that custom functions in OData can be configured as dataServiceContext.Orders/*(DataServiceQuery<Order>)*/.IsComposable == true I apologize if I confused you or if I misunderstood the meaning of English word composable (Capable of being composed (as from multiple lesser elements)). I meant what you wrote: using additional basic OData features like $select. @henrikdahl8240 thank you very much for your insight and help! |
@tomasfabian Thank you for your constructive comments. Your situation sounds quite like mine, i.e. interest/motivation in migrating from .NET Framework to .NET Core. So do you actually have som real success with that, because I actually do not and trust me, I have spent really many hours doing it? For instance I get the problem after switching to 7.4.0 from 7.3.0, that after thousands of invocations of the OData web service in parallel, suddenly the client gets responses like the connection was closed unexpectedly. You have not face that, I mean after many invocations in parallel, which I suppose is within your scope as you do something major, as it sounds like? I am also faced with the issue, that the routing does not select the right method in case of multiple overloads because the first of the given name is trivially being selected. You may see #2075, particularly:
If #2148 would also be relevant to you, perhaps you could drop a "me too" comment there. As far as I understand, concerning "composability" in scope of OData, it basically means h(g(f(x))) where f and g are functions marked as composable. I am sorry if I just waste your time with my questions, but it could just be interesting to hear, if you actually have real success with .NET Core or you are basically stuck with the same shortcomings. |
@henrikdahl8240 just shortly as this is not related to this issue (please contact me via email if you would like to share knowledge). I'm currently using multitargeting - production still uses AspNet.OData (NET472) and in development I'm migrating to AspNetCore.OData (NETCOREAPP3.1). Up to this time I was able to migrate everything except of some operations related to OData batch support. Some bugs were introduced there. I reported these issues under my old account @tfabian. |
@tomasfabian It seems your question was answered. I will close this issue |
Is there a way / is it necessary to execute the serialization of entities to JSON from the database query asynchronously? I think that it would be beneficial to return the thread to the thread pool during execution of the query.
Is this already done by WebApi or OData within a dedicated middleware? If no, can it be overriden?
This should be fast because the query wasn't executed at this point, so I don't use Task in the return value:
Thank you, Tomas
The text was updated successfully, but these errors were encountered: