You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Expected behavior
I don't really know on which side the problem is, but: I expect that if my database connector and linq provider implements Async versions, EnableQuery attribute will use this overloads.
Screenshots
How it's now:
As you see on screenshot, database calls made synchronous
Additional context
Workaround was created in case anybody need it, but I hope it will be fixed inside library
/// <summary>/// It's workaround for OData EnableQuery attribute that forces to use synchronous database calls instead of async version/// this code was used from: https://github.com/OData/WebApi/issues/2598/// and: https://github.com/OData/WebApi/issues/2325/// </summary>publicsealedclassEnableQueryAsyncAttribute:EnableQueryAttribute{privatestaticreadonlyMethodInfoReadInternalMethod=typeof(EnableQueryAsyncAttribute).GetMethods(BindingFlags.Static | BindingFlags.NonPublic).Single(method => method.Name == nameof(ReadInternal));publicoverridevoidValidateQuery(HttpRequesthttpRequest,ODataQueryOptionsqueryOptions){
httpRequest.HttpContext.Items["_ODataQueryOptions"]=queryOptions;base.ValidateQuery(httpRequest, queryOptions);}publicoverrideasync Task OnResultExecutionAsync(ResultExecutingContextcontext,ResultExecutionDelegatenext){if(context.Result is ObjectResult { Value: IQueryable queryable } objectResult){varcancellationToken= context.HttpContext.RequestAborted;varqueryOptions= context.HttpContext.Items["_ODataQueryOptions"]as ODataQueryOptions;varrequest= context.HttpContext.Request;//if $count is included in queryif(queryOptions?.Count is{ Value:true}){varfilteredQueryable=(queryOptions.Filter ==null?queryable: queryOptions.Filter.ApplyTo(queryable,new ODataQuerySettings()))asIQueryable<dynamic>;varcount=await filteredQueryable.LongCountAsync(cancellationToken).ConfigureAwait(false);// Setting the TotalCount causes oData to not execute the TotalCountFunc.
request.ODataFeature().TotalCount =count;if(count==0){// No need to have oData execute the queryable.varinstance= Activator.CreateInstance(typeof(List<>).MakeGenericType(queryable.ElementType));
objectResult.Value =new OkObjectResult(instance);}}//asynchronous call to db for resultsvarqueryableType= queryable.GetType();if(queryableType.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition()==typeof(IAsyncEnumerable<>))){varreadInternalMethod= ReadInternalMethod.MakeGenericMethod(queryableType.GenericTypeArguments[0]);varinvoked= readInternalMethod.Invoke(null,newobject[]{ queryable, cancellationToken })!;varresult=await(Task<ICollection>)invoked;
objectResult.Value =result;}}_=await next().ConfigureAwait(false);}privatestaticasyncTask<ICollection>ReadInternal<T>(objectvalue,CancellationTokencancellationToken){varasyncEnumerable=(IAsyncEnumerable<T>)value;varresult=newList<T>();awaitforeach(var item in asyncEnumerable.WithCancellation(cancellationToken)){
cancellationToken.ThrowIfCancellationRequested();
result.Add(item);}returnresult;}}
Forevka
changed the title
Asynchronous calls to database with EnableQuery attribute [with workaround solution]
Asynchronous calls to database with EnableQuery attribute [workaround solution]
Oct 16, 2024
Assemblies affected
ASP.NET Core OData 8.x and ASP.NET Core OData 9.x
Describe the bug
All database calls that are made in order to fetch data from IQueryable<> that returned from controller route are made synchronous
Reproduce steps
Data Model
Sample model (but it's don't really matter)
Expected behavior
I don't really know on which side the problem is, but: I expect that if my database connector and linq provider implements Async versions, EnableQuery attribute will use this overloads.
Screenshots
How it's now:
As you see on screenshot, database calls made synchronous
Additional context
Workaround was created in case anybody need it, but I hope it will be fixed inside library
How to use:
result:
all calls are made async
The text was updated successfully, but these errors were encountered: