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

SumAsync throw Exception when used over float? #12314

Closed
iyhammad opened this issue Jun 9, 2018 · 2 comments
Closed

SumAsync throw Exception when used over float? #12314

iyhammad opened this issue Jun 9, 2018 · 2 comments
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Milestone

Comments

@iyhammad
Copy link

iyhammad commented Jun 9, 2018

SumAsync is throwing
System.InvalidOperationException: No coercion operator is defined between types 'System.Threading.Tasks.Task`1[System.Single]' and 'System.Nullable`1[System.Single]'.
when using it over an owned type. when used with float? after upgrading from EFCore 2.0 to 2.1

Exception Details

No coercion operator is defined between types 'System.Threading.Tasks.Task`1[System.Single]' and 'System.Nullable`1[System.Single]'.
System.InvalidOperationException: No coercion operator is defined between types 'System.Threading.Tasks.Task`1[System.Single]' and 'System.Nullable`1[System.Single]'.
   at System.Linq.Expressions.Expression.GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType)
   at System.Linq.Expressions.Expression.Convert(Expression expression, Type type, MethodInfo method)
   at Microsoft.EntityFrameworkCore.Query.Internal.RelationalResultOperatorHandler.HandleSum(HandlerContext handlerContext)
   at Microsoft.EntityFrameworkCore.Query.Internal.RelationalResultOperatorHandler.HandleResultOperator(EntityQueryModelVisitor entityQueryModelVisitor, ResultOperatorBase resultOperator, QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, Int32 index)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, Int32 index)
   at Remotion.Linq.Clauses.ResultOperatorBase.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
   at Remotion.Linq.QueryModelVisitorBase.VisitResultOperators(ObservableCollection`1 resultOperators, QueryModel queryModel)
   at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateAsyncQueryExecutor[TResult](QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileAsyncQuery[TResult](QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileAsyncQueryCore[TResult](Expression query, IQueryModelGenerator queryModelGenerator, IDatabase database)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass22_0`1.<CompileAsyncQuery>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddAsyncQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileAsyncQuery[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.SumAsync(IQueryable`1 source, CancellationToken cancellationToken)
   at HRPayroll.Leave.Data.EntityFramework.Repositories.LeaveRequestRepository.<GetLeavesSumAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Abp.Threading.InternalAsyncHelper.<AwaitTaskWithPostActionAndFinallyAndGetResult>d__5`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at HrPayroll.Leave.Core.LeaveBalance.LeaveBalanceService.<GetEmployeeLeaveConsumptionAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at HrPayroll.Leave.Core.LeaveBalance.LeaveBalanceService.<GetEmployeeLeaveBalanceToDateAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at HrPayroll.Leave.Application.LeaveBalances.LeaveBalanceApplicationService.<GetEmployeeLeavesBalancesToDate>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at lambda_method(Closure , Object )
   at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.AwaitableObjectResultExecutor.<Execute>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()

Steps to reproduce

  1. Define an owned entity with float? property
  2. Define and an owner entity
  3. Call SumAsyn using the Owner Set to sum the owned entity field.
    below the same owner & owned entities and the exception happens only with the SumAsync

##LeaveRequestRepository .cs

 var sumLeavsFullyPaid =
                this.Context.Set<LeaveRequest>()
                    .Where(predicate).Select(z => z.TakenBalance.FullyPaid).Sum(); // success
            var sumPartiallyPaid = await
                this.Context.Set<LeaveRequest>()
                    .Where(predicate).Select(z => z.TakenBalance.PartiallyPaid).SumAsync().ConfigureAwait(false); //throw exception

Further technical details

EF Core version: 2.1.0
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10 Enterprise, Build: 17134.48
IDE: Visual Studio 2017 15.7.3

@iyhammad iyhammad changed the title SumAsync throw Exception when used over owned type SumAsync throw Exception when used over float? Jun 9, 2018
@ajcvickers ajcvickers added this to the 2.1.3 milestone Jun 12, 2018
@maumar
Copy link
Contributor

maumar commented Jun 13, 2018

regression introduced in 4bb6c38 - in order to produce 0 for sum of empty collections we strip the nullability and then try to cast the result back to nullable. This doesn't work for async because Task, hence the exception.

maumar added a commit that referenced this issue Jun 13, 2018
Problem was that in order to return 0 from empty Sum of nullable values, we convert them to non-nullable (to produce 0) and then convert back to nullable type. This works without issue for sync path, but in async simple casting like that doesn't work.

Fix is to call method that adds Task.ContinueWith() call that casts the result to the correct type in the async scenario.
maumar added a commit that referenced this issue Jun 14, 2018
Problem was that in order to return 0 from empty Sum of nullable values, we convert them to non-nullable (to produce 0) and then convert back to nullable type. This works without issue for sync path, but in async simple casting like that doesn't work.

Fix is to call method that adds Task.ContinueWith() call that casts the result to the correct type in the async scenario.
maumar added a commit that referenced this issue Jun 19, 2018
Problem was that in order to return 0 from empty Sum of nullable values, we convert them to non-nullable (to produce 0) and then convert back to nullable type. This works without issue for sync path, but in async simple casting like that doesn't work.

Fix is to call method that adds Task.ContinueWith() call that casts the result to the correct type in the async scenario.
@ajcvickers ajcvickers added type-bug closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. Servicing-consider patch-approved and removed type-investigation Servicing-consider labels Jun 20, 2018
@ajcvickers
Copy link
Member

@maumar This issue is approved for patch and the release\2.1 branch is now open for merging. Please ensure:

  • The appropriate changes get into both the release and dev branches
  • Quirking is included for the release branch only

maumar added a commit that referenced this issue Jun 29, 2018
Problem was that in order to return 0 from empty Sum of nullable values, we convert them to non-nullable (to produce 0) and then convert back to nullable type. This works without issue for sync path, but in async simple casting like that doesn't work.

Fix is to call method that adds Task.ContinueWith() call that casts the result to the correct type in the async scenario.
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 regression type-bug
Projects
None yet
Development

No branches or pull requests

3 participants