Base solution for your next web application
Open Closed

Abp.EntityFrameworkCore 9.3 bug? Async operations for the LINQ provider 'Abp.EntityFrameworkCore.AbpEntityQueryProvider' are not supported #12105


User avatar
0
uxabp created

When I was using Abp.ZeroCore.EntityFrameworkCore v9.2.2, everything worked fine, but after upgrading to ABP Zero v13.3.0 (rel) (Abp.ZeroCore.EntityFrameworkCore v9.3.0), the same program started encountering errors.

my code:

var dataQuery = _keyValueBucketRepository.GetAll();
dataQuery.WhereIf(!await _commonFunctionManager.IsCurrentUserInRoleAsync(AbpRoles.Role_Admin), x => x.CreatorUserId == _session.GetUserId());
var result = await DataSourceLoader.LoadAsync(dataQuery, loadOptions);   // this line failed

error result

ERROR 2024-08-05 15:13:39,300 [10   ] Mvc.ExceptionHandling.AbpExceptionFilter - Async operations for the LINQ provider 'Abp.EntityFrameworkCore.AbpEntityQueryProvider' are not supported. You can implement a custom async adapter (DevExtreme.AspNet.Data.Async.IAsyncAdapter) and register it via 'DevExtreme.AspNet.Data.Async.CustomAsyncAdapters.RegisterAdapter'.
System.NotSupportedException: Async operations for the LINQ provider 'Abp.EntityFrameworkCore.AbpEntityQueryProvider' are not supported. You can implement a custom async adapter (DevExtreme.AspNet.Data.Async.IAsyncAdapter) and register it via 'DevExtreme.AspNet.Data.Async.CustomAsyncAdapters.RegisterAdapter'.at DevExtreme.AspNet.Data.ExpressionExecutor.CreateAsyncAdapter()at DevExtreme.AspNet.Data.ExpressionExecutor.ToEnumerableAsyncTat DevExtreme.AspNet.Data.DataSourceLoaderImpl1.ExecExprAsync[R](Expression expr) at DevExtreme.AspNet.Data.DataSourceLoaderImpl1.LoadAsync()at MyCompanyName.AbpZeroTemplate.ProjectExtension.DevAppServices.DevSftpManagersAppService.GetAll(DataSourceLoadOptions loadOptions) in C:\ABP\MikroTikBackupManager\aspnet-core\src\MyCompanyName.AbpZeroTemplate.Application\ProjectExtension\DevAppServices\DevSftpManagersAppService.cs:line 106at lambda_method3306(Closure, Object)at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Logged|12_1(ControllerActionInvoker invoker)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

5 Answer(s)
  • User Avatar
    0
    m.aliozkaya created
    Support Team

    Hi @uxabp,

    Could you share your project with [email protected]?

  • User Avatar
    0
    uxabp created

    Hi @uxabp,

    Could you share your project with [email protected]?

    Hi @m.aliozkaya,

    Due to the project involving the company's internal business secrets, I am unable to share it. However, I can explain the components I used. Since the development needs to continue, I have reverted to the old version for now.

    ABP Zero (with GitHub dev 2024/7/12) Core MVC & jQuery Project DevExpress 24.1.3 using Html.DevExtreme().DataGrid

    Code

    [DontWrapResult(WrapOnError = true, WrapOnSuccess = false, LogError = true)]
    [HttpGet]
    public async Task<JsonResult> GetAll(DataSourceLoadOptions loadOptions)
    {
        var dataQuery = _metricsProxyRepository.GetAll();
        dataQuery = dataQuery.WhereIf(!await _commonDomainService.IsCurrentUserInRoleAsync(AbpRoles.Role_Admin), x => x.CreatorUserId == _session.GetUserId());
    
        var result = await DataSourceLoader.LoadAsync(dataQuery, loadOptions);  //HERE ABP v9.3.0 Error
        if (loadOptions.Group == null)
        {
            result.data = ObjectMapper.Map<List<DevCarDto>>(result.data);
        }
        return new JsonResult(result, JsonSerializerOptionsCollection.DefaultOptions);
    }
    

    ABP v9.2.2 was working fine, but after upgrading to ABP v9.3.0, the same program started having errors(see //HERE ABP v9.3.0 Error).

    Using Abp.ZeroCore.EntityFrameworkCore v9.3.0 ERROR Message:
    
    Async operations for the LINQ provider 'Abp.EntityFrameworkCore.AbpEntityQueryProvider' are not supported. 
    You can implement a custom async adapter (DevExtreme.AspNet.Data.Async.IAsyncAdapter) and register it via 'DevExtreme.AspNet.Data.Async.CustomAsyncAdapters.RegisterAdapter'.
    

    I estimate that users of DevExpress will be affected. It would be great if you could help. Regardless, thank you for response.

  • User Avatar
    0
    maliming created
    Support Team

    hi @uxabp,

    Can you try the code below?

    
    //Add these lines to your ef core module Initialize method.
    var adapter = new AbpDevExtremeAsyncAdapter();
    CustomAsyncAdapters.RegisterAdapter(typeof(AbpEntityQueryProvider), adapter);
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Threading;
    using System.Threading.Tasks;
    using DevExtreme.AspNet.Data.Async;
    
    namespace Abp.EntityFrameworkCore;
    
    public class AbpDevExtremeAsyncAdapter : IAsyncAdapter
    {
        private readonly MethodInfo _countAsyncMethod;
        private readonly MethodInfo _toListAsyncMethod;
    
        public AbpDevExtremeAsyncAdapter()
        {
            var extensionsType = Type.GetType("Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions, Microsoft.EntityFrameworkCore");
            _countAsyncMethod = FindQueryExtensionMethod(extensionsType, "CountAsync");
            _toListAsyncMethod = FindQueryExtensionMethod(extensionsType, "ToListAsync");
        }
    
        public Task<int> CountAsync(IQueryProvider provider, Expression expr, CancellationToken cancellationToken)
        {
            return InvokeCountAsync(_countAsyncMethod, provider, expr, cancellationToken);
        }
    
        public Task<IEnumerable<T>> ToEnumerableAsync<T>(IQueryProvider provider, Expression expr, CancellationToken cancellationToken)
        {
            return InvokeToListAsync<T>(_toListAsyncMethod, provider, expr, cancellationToken);
        }
    
        static MethodInfo FindQueryExtensionMethod(Type extensionsType, string name)
        {
            return extensionsType.GetMethods().First(m =>
            {
                if (!m.IsGenericMethod || m.Name != name)
                {
                    return false;
                }
                var parameters = m.GetParameters();
                return parameters.Length == 2 && parameters[1].ParameterType == typeof(CancellationToken);
            });
        }
    
        static Task<int> InvokeCountAsync(MethodInfo method, IQueryProvider provider, Expression expr, CancellationToken cancellationToken)
        {
            var countArgument = ((MethodCallExpression)expr).Arguments[0];
            var query = provider.CreateQuery(countArgument);
            return (Task<int>)InvokeQueryExtensionMethod(method, query.ElementType, query, cancellationToken);
        }
    
        static async Task<IEnumerable<T>> InvokeToListAsync<T>(MethodInfo method, IQueryProvider provider, Expression expr, CancellationToken cancellationToken)
        {
            return await (Task<List<T>>)InvokeQueryExtensionMethod(method, typeof(T), provider.CreateQuery(expr), cancellationToken);
        }
    
        static object InvokeQueryExtensionMethod(MethodInfo method, Type elementType, IQueryable query, CancellationToken cancellationToken)
        {
            return method.MakeGenericMethod(elementType).Invoke(null, new object[] { query, cancellationToken });
        }
    }
    
    
  • User Avatar
    0
    uxabp created

    hi @uxabp,

    Can you try the code below?

    The program works, thank you.

  • User Avatar
    0
    maliming created
    Support Team

    : )