zzzprojects / System.Linq.Dynamic.Core

The .NET Standard / .NET Core version from the System Linq Dynamic functionality.
https://dynamic-linq.net/
Apache License 2.0
1.55k stars 227 forks source link

Exception after upgrade to .net core 3 #317

Open MoRooz opened 4 years ago

MoRooz commented 4 years ago

this is source of exception

q2.Select("new(Key.CallItemStatus as CallItemStatus, it.Count() as Count))")

the same code works fine in .net core 2.2

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'index')
   at System.Linq.Expressions.InstanceMethodCallExpression1.GetArgument(Int32 index)
   at System.Dynamic.Utils.ListArgumentProvider.GetElement(Int32 index)
   at System.Dynamic.Utils.ListProvider`1.get_Item(Int32 index)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityEqualityRewritingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityEqualityRewritingExpressionVisitor.<VisitMemberInit>g__VisitMemberBindings|9_0(ReadOnlyCollection`1 bindings)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityEqualityRewritingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
   at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression`1 node)
   at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityEqualityRewritingExpressionVisitor.VisitUnary(UnaryExpression unaryExpression)
   at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityEqualityRewritingExpressionVisitor.VisitSelectMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityEqualityRewritingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityEqualityRewritingExpressionVisitor.Rewrite(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
   at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at System.Linq.Dynamic.Core.DynamicEnumerableExtensions.CastToList[T](IEnumerable source)
   at System.Linq.Dynamic.Core.DynamicEnumerableAsyncExtensions.<>c__DisplayClass7_0`1.<CastToListAsync>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
StefH commented 4 years ago

@MoRooz If possible, provide a full working sample project.

MoRooz commented 4 years ago

DynamicLinqNetCore3Test.zip

StefH commented 4 years ago

When calling ToArray() on the q1 like:

var q1 = context.Blogs.GroupBy(context.Blogs.KeySelectorExpression(groupByList));
var q1a = q1.ToArray();

Already gives an exception:

System.InvalidOperationException: 'Client projection contains reference to constant expression of type: Microsoft.EntityFrameworkCore.Metadata.IPropertyBase. This could potentially cause memory leak.'

StefH commented 4 years ago

See also

When upgrading to 3.1 preview, I get this better error:

System.InvalidOperationException: 'Client projection contains reference to constant expression of 'Microsoft.EntityFrameworkCore.Metadata.IPropertyBase' which is being passed as argument to method 'TryReadValue'. This could potentially cause memory leak. Consider assigning this constant to local variable and using the variable in the query instead. See https://go.microsoft.com/fwlink/?linkid=2103067 for more information.'

MoRooz commented 4 years ago

memory leak is probably because of InMemory Provider, here is Sqlite one, with another error

Client side GroupBy is not supported

var options = new DbContextOptionsBuilder<BloggingContext>().UseSqlite("Filename=MyDatabase.db").Options;

            using (var context = new BloggingContext(options))
            {
                context.Database.EnsureCreated();

                context.Blogs.Add(new Blog { CategoryId = 1, PageId = 2 });
                context.Blogs.Add(new Blog { CategoryId = 1, PageId = 3 });
                context.Blogs.Add(new Blog { CategoryId = 2, PageId = 2 });
                context.Blogs.Add(new Blog { CategoryId = 2, PageId = 2 });
                context.SaveChanges();

                // not working
                var groupByList = new List<string> { "CategoryId" };
                var q1 = context.Blogs.GroupBy(context.Blogs.KeySelectorExpression(groupByList));
                //var q11List = q1.ToArray();

                var q3 = System.Linq.Dynamic.Core.DynamicQueryableExtensions.GroupBy(context.Blogs, "CategoryId");
                var q31List = q3.ToDynamicArray();

                var q2 = q1.Select("new (Key.CategoryId as CategoryId, it.Count() as Count)");
                //var q2 = q1.Select("new (it.Key.CategoryId as CategoryId, it.Count() as Count)");
                var result0 = q2.ToDynamicList<object>();

                // working
                var g0 = context.Blogs.GroupBy("new (CategoryId)");
                var g1 = g0.Select("new (it.Key.CategoryId as CategoryId, it.Count() as Count)");
                var list = g1.ToDynamicList<object>();
            }

both LinqGroupBy and DynamicLinq GroupBy has this error

MoRooz commented 4 years ago

seems some sql aggregate is necessary in select

https://github.com/aspnet/EntityFrameworkCore/issues/18102#issuecomment-536231179

this is working,


var groupByList = new List<string> { "CategoryId","PageId" };
var q2 = context.Blogs.GroupBy(context.Blogs.KeySelectorExpression(groupByList)).Select("new (it.Key as Key, it.Count() as Count)");
var q2List = q2.ToDynamicList<object>();

now only if its possible to get flatten key.

current

{{ Key = { CategoryId = 1, PageId = 2 }, Count = 34 }}

need (used to work in net 2.2 with Key.Property in select)

{{ CategoryId = 1, PageId = 2, Count = 34 }}
StefH commented 4 years ago

@MoRooz Thanks for researching. Would it be an idea to add this in a readable markdown format in a wiki? If so, can you please help.