question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Exception when filtering on many to many

See original GitHub issue

Hi, I am not sure if it’s an issue with my code or the library. I have a model that has several one to many and one many to many navigation properties

When filtering on the one to many I get the expected results. However if I try filtering on the many to many I get an exception, This is my query: https://localhost:5001/api/incidents?$expand=personType, location, incidentType, eventTypes & $filter=deleted eq false and location/name eq ‘MHC’ or eventTypes/any(e:e/id eq d98d3c8e-6951-402f-ab3d-c2fcedc24171)

This is the mapping

 CreateMap<Report, ReportDTO>()
            .ForMember(dto => dto.EventTypes, opt => opt
                .MapFrom(src => src.IncidentEventTypes.Select(i => i.EventType).ToList())
            );
            
           CreateMap<ReportDTO, Report>()
            // this is to prevent actions to be submitted up
            .ForMember(d => d.Location, opt => opt.Ignore())
            .ForMember(d => d.PersonType, opt => opt.Ignore())
            .ForMember(d => d.IncidentType, opt => opt.Ignore())
            .ForMember(d => d.LocationId, opt => opt.MapFrom(src => src.Location.Id))
            .ForMember(d => d.PersonTypeId, opt => opt.MapFrom(src => src.PersonType.Id))
            .ForMember(d => d.IncidentTypeId, opt => opt.MapFrom(src => src.IncidentType.Id))
            .ForMember(d => d.IncidentEventTypes, opt => opt
                .MapFrom((src, dst) => src.EventTypes
                    .Select(eventType => 
                        new IncidentEventType() {ReportId = dst.Id, EventTypeId = eventType.Id })
                    .ToList()
                )
            )
            .ForMember(d => d.CreatedDate, opt => opt.Ignore())
            .EqualityComparison((odto, o) => odto.Id == o.Id);

this is the exception: “Expression of type ‘System.Collections.Generic.List1[Benton.HealthIR.Models.EventType]' cannot be used for parameter of type 'System.Linq.IQueryable1[Benton.HealthIR.Models.EventType]’ of method ‘Boolean Any[EventType](System.Linq.IQueryable1[Benton.HealthIR.Models.EventType], System.Linq.Expressions.Expression1[System.Func`2[Benton.HealthIR.Models.EventType,System.Boolean]])’ (Parameter ‘arg0’)”

this is the stack: " at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)\r\n at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1)\r\n at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable1 arguments)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.EnumerableToQueryableMethodConvertingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)\r\n at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitUnary(UnaryExpression node)\r\n at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitConditional(ConditionalExpression node)\r\n at System.Linq.Expressions.ConditionalExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)\r\n at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)\r\n at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression1 node)\r\n at System.Linq.Expressions.Expression1.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitUnary(UnaryExpression node)\r\n at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)\r\n at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)\r\n at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)\r\n at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)\r\n at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)\r\n at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)\r\n at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)\r\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\r\n at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)\r\n at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)\r\n at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_01.<ExecuteAsync>b__0()\r\n at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func1 compiler)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func1 compiler)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1.GetAsyncEnumerator(CancellationToken cancellationToken)\r\n at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.IncludableQueryable2.GetAsyncEnumerator(CancellationToken cancellationToken)\r\n at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable1.GetAsyncEnumerator()\r\n at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable1 source, CancellationToken cancellationToken)\r\n at AutoMapper.AspNet.OData.QueryableExtensions.GetAsync[TModel,TData](IQueryable1 query, IMapper mapper, Expression1 filter, Expression1 queryFunc, ICollection1 includeProperties)\r\n at AutoMapper.AspNet.OData.QueryableExtensions.GetAsync[TModel,TData](IQueryable1 query, IMapper mapper, ODataQueryOptions1 options, HandleNullPropagationOption handleNullPropagation)\r\n at Benton.HealthIR.API.Controllers.IncidentsController.GetIncidents(ODataQueryOptions`1 options, Boolean restrict) in C:\Repos\HealthIR-Odata\HealthIR\API\Controllers\IncidentController.cs:line 71"

I think it has to do with the mapping but i am not certain. Any help is greatly appreciated

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
BlaiseDcommented, Mar 26, 2020

The mapping looks correct. You may want to post a question to the EF Core Repo - I see a similar issue has been posted before.

However, disabling null checks does simplify the filter expression: return Ok(await query.GetAsync(_mapper, options, HandleNullPropagationOption.False)); - which does not throw the exception.

With null handling:

            Expression<Func<ReportDTO, bool>> filterNullHandling = it => 
            (
                IIF
                (
                    (it.EventTypes == null),
                    null,
                    Convert
                    (
                        it.EventTypes.Any
                        (
                            e => 
                                (
                                    IIF((e == null), null, e.Name)  
                                    ==  
                                    value(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer + TypedLinqParameterContainer`1[System.String]).TypedProperty
                                )
                        ), Nullable`1
                    )
                ) == True
            );

maps to:

            Expression<Func<Report, bool>> filterMappedNullHandling = it => 
            (
                IIF
                (
                    (it.IncidentEventTypes.Select(i => i.EventType) == null),
                    null, 
                    Convert
                    (
                        it.IncidentEventTypes.Select(i => i.EventType).Any
                        (
                            e => 
                            (
                                IIF((e == null), null, e.Name) 
                                == 
                                value(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer + TypedLinqParameterContainer`1[System.String]).TypedProperty
                            )
                        ), Nullable`1
                    )
                ) == True
            );

Without null handling:

            Expression<Func<ReportDTO, bool>> filter = it => it.EventTypes.Any
            (
                e => 
                (
                    e.Name 
                    == 
                    value(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer + TypedLinqParameterContainer`1[System.String]).TypedProperty
                )
            );

maps to:

            Expression<Func<Report, bool>> filterMapped = it => it.IncidentEventTypes
                    .Select(i => i.EventType)
                    .Any
                    (
                        e => 
                        (
                            e.Name 
                            == 
                            value(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer + TypedLinqParameterContainer`1[System.String]).TypedProperty
                        )
                    );

In both cases the conversions look correct. It looks to me as if EF Core doesn’t like the more complex expression.

0reactions
DarthBertcommented, Mar 26, 2020

Thank you!!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Filtering on many-to-many relations that fulfill a set of criteria
A simple solution: order_operations = OrderOperation.objects.all() for article in articles: order_operations ...
Read more >
Filters Not Working with Many to Many Relationship
Filters Not Working with Many to Many Relationship ... I'm getting the error 'the cardinality you selected isn't valid for this relationship ......
Read more >
Filtering by many to many relation throws an exception #49
Trying to implement filtering resource by its relationship column, but it throws an exception Expecting pivot filter to be used with a ...
Read more >
Filtering a many-to-many relationship
This seems to be a standard many-to-many relationship. I'd like to see the map of the LOCALITIES but filtered by the EXPEDITIONS.
Read more >
How to filter this ManyToMany relation?
It's better to do the relationship traversing in the database rather than iterating over the collections in python (checkout these docs for more ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found