jeudi 13 décembre 2018

LINQ, Entity Framework and Reflection: getting an ArgumentException

I have a list of objects that have relations on which I want to get all the ones having none (so the ones not used).

I first get all the properties that are collections and then use this in a Where clause :

List<System.Reflection.PropertyInfo> collectionsProperties = 
    typeof(DAL.Entities.File).GetProperties()
                             .Where(p => p.PropertyType.IsGenericType && 
                                         p.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>))
                             .ToList<System.Reflection.PropertyInfo>();

var files = await _context.Files
                          .Where(f => collectionsProperties.Where(p => (p.GetValue(f) as System.Collections.IEnumerable).Cast<object>().Count() != 0).Count() == 0)
                          .ToListAsync();

I get an ArgumentException and I found no hint on why I get this. I tested my where clause getting two objects (one not used, one yes) and it works correctly.

var fileUsed = await _context.Files.Include(i => i.FileClips).FirstOrDefaultAsync(f => f.Id == 29870);
var fileNotUsed = _context.Files.Include(i => i.DirectoryFloors).Where(f => f.Id == 37949).First();
var isFileNotUsed1 = collectionsProperties.Where(p => (p.GetValue(fileUsed) as System.Collections.IEnumerable).Cast<object>().Count() != 0).Count() == 0;
var isFileNotUsed2 = collectionsProperties.Where(p => (p.GetValue(fileNotUsed) as System.Collections.IEnumerable).Cast<object>().Count() != 0).Count() == 0;

It gives me isFileNotUsed1 false and the second true, which is what I expect.

Does any one of you having experience using Reflection in Where clause?

EDIT-1: Full exception

e.Source = "Microsoft.EntityFrameworkCore"

e.HResult = -2147024809

System.ArgumentException: La valeur n'est pas comprise dans la plage attendue.
    à System.SharedTypeExtensions.GetSequenceType(Type type)
    à Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel)
    à Remotion.Linq.Clauses.MainFromClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel)
    à Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalEntityQueryableExpressionVisitor.VisitSubQuery(SubQueryExpression expression)
    à Remotion.Linq.Clauses.Expressions.SubQueryExpression.Accept(ExpressionVisitor visitor)
    à System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
    à System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
    à System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
    à System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
    à Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.ReplaceClauseReferences(Expression expression, IQuerySource querySource, Boolean inProjection)
    à Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
    à Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
    à Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
    à Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
    à Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalEntityQueryableExpressionVisitor.VisitSubQuery(SubQueryExpression expression)
    à Remotion.Linq.Clauses.Expressions.SubQueryExpression.Accept(ExpressionVisitor visitor)
    à System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
    à System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
    à System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
    à System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
    à Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.ReplaceClauseReferences(Expression expression, IQuerySource querySource, Boolean inProjection)
    à Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
    à Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
    à Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
    à Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
    à Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateAsyncQueryExecutor[TResult](QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Storage.Database.CompileAsyncQuery[TResult](QueryModel queryModel)
    à Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileAsyncQueryCore[TResult](Expression query, IQueryModelGenerator queryModelGenerator, IDatabase database)
    à Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass22_0`1.<CompileAsyncQuery>b__0()
    à Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
    à Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddAsyncQuery[TResult](Object cacheKey, Func`1 compiler)
    à Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileAsyncQuery[TResult](Expression query)
    à Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query)
    à Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression)
    à Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.System.Collections.Generic.IAsyncEnumerable<TResult>.GetEnumerator()
    à System.Linq.AsyncEnumerable.<Aggregate_>d__6`3.MoveNext()
    --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    à System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
    à Itesmedia.ItesLive.BusinessLayer.Files.FilesServices.<GetFilesUnusedAsync>d__3.MoveNext()
    --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    à System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
    à Itesmedia.ItesLive.Iclient.Core.Jobs.CleanUselessFiles.<_Execute>d__0.MoveNext()





Aucun commentaire:

Enregistrer un commentaire