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

Argument types don't match for queries projecting conditional expression with anonymous type result #8315

Closed
sethen opened this issue Apr 27, 2017 · 11 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

@sethen
Copy link

sethen commented Apr 27, 2017

I am using a query in my repository which you can view at this gist: https://gist.github.com/sethen/c1f3cb54e50eb36b696a1f4d79d1670c#file-gistfile1-txt-L23 which is similar to the query I found in issue #5522 -- unfortunately I am still getting the same error. Here is my stack trace:

fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HL4DOE8S2AI2": An unhandled exception was thrown by the application.
System.ArgumentException: Argument types do not match
   at System.Linq.Expressions.Expression.Condition(Expression test, Expression ifTrue, Expression ifFalse, Type type)
   at System.Linq.Expressions.ConditionalExpression.Update(Expression test, Expression ifTrue, Expression ifFalse)
   at System.Linq.Expressions.ConditionalExpression.Accept(ExpressionVisitor visitor)
   at Remotion.Linq.Parsing.ThrowingExpressionVisitor.Visit(Expression expression)
   at System.Linq.Enumerable.SelectIListIterator`2.MoveNext()
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
   at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source, Int32& length)
   at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.VisitNew(NewExpression expression)
   at System.Linq.Expressions.NewExpression.Accept(ExpressionVisitor visitor)
   at Remotion.Linq.Parsing.ThrowingExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalProjectionExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitSelectClause(SelectClause selectClause, 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.CreateQueryExecutor[TResult](QueryModel queryModel)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](Expression query, INodeTypeProvider nodeTypeProvider, IDatabase database, ILogger logger, Type contextType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Remotion.Linq.QueryableBase`1.System.Collections.IEnumerable.GetEnumerator()
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
   at Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter.WriteObject(TextWriter writer, Object value)
   at Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter.<WriteResponseBodyAsync>d__9.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 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeResultAsync>d__32.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 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeResultFilterAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeAllResultFiltersAsync>d__29.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 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeResourceFilterAsync>d__23.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeAsync>d__18.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 Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.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 Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.<Invoke>d__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 Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame`1.<RequestProcessingAsync>d__2.MoveNext()
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 1016.3886ms 200 application/json; charset=utf-8

Essentially I just want to be able to work with nullable properties on my models in a sane way. The issue referenced said that this was fixed but I have tried many ways to get around this and nothing is working.

Further technical details

EF Core version: (found in project.json or packages.config) 1.1.0
Database Provider: Microsoft.EntityFrameworkCore.Sqlite
Operating system: macOS Sierra
IDE: VSCode

@sethen
Copy link
Author

sethen commented Apr 27, 2017

Tried upgrading to 1.1.1 to see if it would fix the issue but it didn't.

@smitpatel
Copy link
Contributor

@sethen - Please share your DbContext & model classes esp. Analysis, Comment, Game, Reward, Matchup.

@sethen
Copy link
Author

sethen commented May 5, 2017

Sorry it took so long for me to respond, I have been busy. Here are the files you requested.

@smitpatel
Copy link
Contributor

@sethen - Thank you for the files. There were few missing pieces but I was able to fill in the blanks and get a repro. I will investigate further to find the root cause.

@smitpatel
Copy link
Contributor

Offending query:

var analysis = db.Analysis.Select(a => new
                                        {
                                            id = a.AnalysisId,
                                            reward = a.RewardId.HasValue
                                                ? new {user_id = a.Reward.UserId}
                                                : null
                                        })
    .ToList();

Classes

public class Reward
{
    public int Id { get; set; }
    public int AnalysisId { get; set; }
    public int UserId { get; set; }
}

public class Analysis
{
    public int AnalysisId { get; set; }
    public int? RewardId { get; set; }
    public Reward Reward { get; set; }
}

Optional nav.

@smitpatel
Copy link
Contributor

Assigning to @maumar

@maumar maumar changed the title Argument types don't match Argument types don't match for queries projecting conditional expression with anonymous type result May 6, 2017
maumar added a commit that referenced this issue May 6, 2017
…itional expression with anonymous type result

Problem was that when translating anonymous type we change the expression type from the anonymous type to Expression[].
In case of conditional expression, if the second result is null constant, it's type stays the same, and when we try to update ConditionalExpression, type mismatch is thrown.

Fix is to recognize the pattern and force client eval for this case, since we cant map objects of type Expression[] anyway.
@smitpatel smitpatel assigned maumar and unassigned smitpatel May 8, 2017
maumar added a commit that referenced this issue May 9, 2017
…itional expression with anonymous type result

Initial problem was that when translating anonymous type we change the expression type from the anonymous type to Expression[].
In case of conditional expression, if the second result is null constant, it's type stays the same, and when we try to update ConditionalExpression, type mismatch is thrown.
However, even if the types are compensated for, we can't translate NewExpression to SQL, apart from it being used in comparison (e.g. in composite key join scenarios)

Fix is to recognize the pattern and force client eval.

Also fixes small bug around alias generation.
maumar added a commit that referenced this issue May 9, 2017
…itional expression with anonymous type result

Initial problem was that when translating anonymous type we change the expression type from the anonymous type to Expression[].
In case of conditional expression, if the second result is null constant, it's type stays the same, and when we try to update ConditionalExpression, type mismatch is thrown.
However, even if the types are compensated for, we can't translate NewExpression to SQL, apart from it being used in comparison (e.g. in composite key join scenarios)

Fix is to recognize the pattern and force client eval.

Also fixes small bug around alias generation.
maumar added a commit that referenced this issue May 9, 2017
…itional expression with anonymous type result

Initial problem was that when translating anonymous type we change the expression type from the anonymous type to Expression[].
In case of conditional expression, if the second result is null constant, it's type stays the same, and when we try to update ConditionalExpression, type mismatch is thrown.
However, even if the types are compensated for, we can't translate NewExpression to SQL, apart from it being used in comparison (e.g. in composite key join scenarios)

Fix is to recognize the pattern and force client eval.

Also fixes small bug around alias generation.
@maumar
Copy link
Contributor

maumar commented May 9, 2017

Fixed in 521feb5

@maumar maumar closed this as completed May 9, 2017
@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 May 9, 2017
@bricelam bricelam modified the milestones: 2.0.0, 2.0.0-preview2 May 16, 2017
@sethen
Copy link
Author

sethen commented May 16, 2017

Thanks a lot, a few questions:

  • Is there a tentative release date for this fix?
  • Is there a current workaround for this?

@maumar
Copy link
Contributor

maumar commented May 16, 2017

@Eilon might have some info about the dates. In the meantime you should be able to do:

var analysis = db.Analysis.Select(a => new
{
	id = a.AnalysisId,
	(int?)reward = a.Reward.UserId  
})
.ToList()
.Select(a => new { a.id, reward = a.reward != null ? new { user_id = reward } : null }

Basically, you can project the columns that you need in the final result (EF Core will do the null protection logic for you) and then do another Select(...) on the client to convert the flat results into desirable shape.

@Eilon
Copy link
Member

Eilon commented May 17, 2017

2.0.0 preview 2 isn't too far out - next month I think. Or you can grab the nightly builds from https://dotnet.myget.org/gallery/aspnetcore-dev.

@sethen
Copy link
Author

sethen commented Jun 2, 2017

@maumar Thanks for this... I found another way around that seems to fit my use case pretty nicely until this is ready for production. This will fetch the reward and ignore if it's null:

reward = _DBContext.Rewards
    .Where(r => r.AnalysisID == a.AnalysisID)
    .Select(r => new
    {
        id = r.RewardID,
        type = r.RewardType.Type,
        value = r.Value
    })
    .SingleOrDefault()

Not ideal, but until 2.0.0 is ready -- it works.

@ajcvickers ajcvickers removed this from the 2.0.0-preview2 milestone Oct 15, 2022
@ajcvickers ajcvickers added this to the 2.0.0 milestone Oct 15, 2022
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

6 participants