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

EF Core does not cast from Nullable to underlying type #10284

Closed
AndrewBoklashko opened this issue Nov 14, 2017 · 6 comments
Closed

EF Core does not cast from Nullable to underlying type #10284

AndrewBoklashko opened this issue Nov 14, 2017 · 6 comments
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Milestone

Comments

@AndrewBoklashko
Copy link

Having the following mapping:

        public static IQueryable<UserInListDTO> MapToUserInListToDTO(this IQueryable<Parent> parents)
            => parents.Select(p => new UserInListDTO
                {
                    Id = p.Id,
                    FirstName = p.FirstName,
                    LastName = p.LastName,
                    Email = p.ApplicationUser != null
                        ? p.ApplicationUser.Email
                        : null,
                    PhoneNumber = p.ApplicationUser != null
                        ? p.ApplicationUser.PhoneNumber
                        : null,
                    Address = p.Address != null
                        ? p.Address.MappedAddress
                        : null,
                    Schools = p.Childs.Select(c => c.School.SchoolName).Distinct(),
                    Status = p.ApplicationUser != null
                        ? p.ApplicationUser.Status.ToFriendlyString()
                        : null,
                    Verified = p.IsVerified,
                         ....
                });

Query fails with exception on this part:

Status = p.ApplicationUser != null ? p.ApplicationUser.Status.ToFriendlyString() : null

Status property type is enum. Relation beetwen Parent and ApplicationUser:

            builder.Entity<ApplicationUser>()
                .HasOne(u => u.Parent)
                .WithOne(p => p.ApplicationUser)
                .IsRequired()
                .HasForeignKey<ApplicationUser>(u => u.ParentId)
                .OnDelete(DeleteBehavior.Cascade);
System.ArgumentException: Expression of type 'System.Nullable`1[KidsCareApp.Model.Enums.UserStatuses]' cannot be used for parameter of type 'KidsCareApp.Model.Enums.UserStatuses' of method 'System.String ToFriendlyString[UserStatuses](KidsCareApp.Model.Enums.UserStatuses)'
Parameter name: arg0
   at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
   at System.Linq.Expressions.MethodCallExpression.Update(Expression object, IEnumerable`1 arguments)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.Expressions.Internal.NullConditionalExpression.VisitChildren(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.VisitExtension(Expression node)
   at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.VisitMemberAssignment(MemberAssignment node)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
   at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection`1 nodes, Func`2 elementVisitor)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node)
   at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Remotion.Linq.Clauses.SelectClause.TransformExpressions(Func`2 transformation)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ExpressionTransformingQueryModelVisitor`1.VisitSelectClause(SelectClause selectClause, QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.NavigationRewritingQueryModelVisitor.VisitSelectClause(SelectClause selectClause, QueryModel queryModel)
   at Remotion.Linq.Clauses.SelectClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel)
   at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.Rewrite(QueryModel queryModel, QueryModel parentQueryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.OptimizeQueryModel(QueryModel queryModel, Boolean asyncQuery)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.OptimizeQueryModel(QueryModel queryModel, Boolean asyncQuery)
   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, INodeTypeProvider nodeTypeProvider, IDatabase database)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass24_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)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.System.Collections.Generic.IAsyncEnumerable<TResult>.GetEnumerator()
   at System.Linq.AsyncEnumerable.<Aggregate_>d__6`3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at KidsCareApp.Repository.Services.Admin.AdminUserService.<GetUsersAsync>d__1.MoveNext()

Further technical details

EF Core version: 2.0.0
Database Provider: Microsoft.EntityFrameworkCore.SQLServer
Operating system: Windows 10 Pro 1703 15063.540
IDE: Visual Studio 2017

@AndrewBoklashko AndrewBoklashko changed the title EF does not cast from Nullable to underlying type EF Core does not cast from Nullable to underlying type Nov 14, 2017
@anpete
Copy link
Contributor

anpete commented Nov 14, 2017

@maumar Nav expansion?

@maumar
Copy link
Contributor

maumar commented Nov 14, 2017

looks like it

@maumar maumar self-assigned this Nov 14, 2017
@AndrewBoklashko
Copy link
Author

By the way with explicit casting it works:
Status = ((UserStatuses)p.ApplicationUser.Status).ToFriendlyString()

@ajcvickers ajcvickers added this to the 2.1.0 milestone Nov 17, 2017
@ajcvickers ajcvickers modified the milestones: 2.1.0-preview1, 2.1.0 Jan 17, 2018
@maumar
Copy link
Contributor

maumar commented Feb 5, 2018

The problem here is that during nav rewrite we deduce that since Person->ApplicationUser is principal to dependent, ApplicationUser can be null, so we apply null protection logic on the call accessing Status property. This changes the type to Nullable<UserStatuses> which then no longer matches the signature of the method ToFriendlyString that is being called.

@anpete
Copy link
Contributor

anpete commented Feb 5, 2018

@maumar So we should unwrap before calling into client method here? cc @smitpatel

maumar added a commit that referenced this issue Feb 6, 2018
Problem was that we were too aggressive in applying null compensation during navigation rewrite. This could lead to type change of an argument to a function - if the argument was a non-nullable property accessed via optional navigation). This in turn causes issues during compilation, because new method arguments must match method signature.

Fix is to unwrap null compensation for arguments of the function.
maumar added a commit that referenced this issue Feb 7, 2018
Problem was that we were too aggressive in applying null compensation during navigation rewrite. This could lead to type change of an argument to a function - if the argument was a non-nullable property accessed via optional navigation). This in turn causes issues during compilation, because new method arguments must match method signature.

Fix is to unwrap null compensation for arguments of the function.
maumar added a commit that referenced this issue Feb 7, 2018
Problem was that we were too aggressive in applying null compensation during navigation rewrite. This could lead to type change of an argument to a function - if the argument was a non-nullable property accessed via optional navigation). This in turn causes issues during compilation, because new method arguments must match method signature.

Fix is to unwrap null compensation for arguments of the function.
maumar added a commit that referenced this issue Feb 7, 2018
Problem was that we were too aggressive in applying null compensation during navigation rewrite. This could lead to type change of an argument to a function - if the argument was a non-nullable property accessed via optional navigation). This in turn causes issues during compilation, because new method arguments must match method signature.

Fix is to unwrap null compensation for arguments of the function.
@maumar
Copy link
Contributor

maumar commented Feb 7, 2018

fixed in f7e93de

@maumar maumar closed this as completed Feb 7, 2018
@maumar maumar added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Feb 7, 2018
@ajcvickers ajcvickers modified the milestones: 2.1.0-preview2, 2.1.0 Nov 11, 2019
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. type-bug
Projects
None yet
Development

No branches or pull requests

4 participants