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

Where/Select/OrderBy/etc clauses referencing DB types can't execute if helper function used #7808

Closed
acherrymsft opened this issue Mar 8, 2017 · 2 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

@acherrymsft
Copy link

(Terrible name, I'm sorry.)

I encountered this in production code I was switching over from Linq-to-Objects to EntityFramework. Confirmed with both 1.1.0 and 1.1.1 and both UWP and .Net.

When a Select() clause is used to capture and extend data from a DbSet, any usage after the Select clause of the Included field causes the expression compiler to throw on compilation, not execution, rending the Linq statement unusable.

Full code below, but sample version:

                var results = context.Nodes.Include(node => node.Leaf) // also fails if the .Include is excluded
                    .Select(node => Create(node)) // works if replaced with "new ClientQueryObject() { Node = node) }"
                    .Where(clientquery => clientquery.Node.Leaf != null) // Also fails with OrderBy, Select, etc. -- as long as it references clientQuery.Node.Leaf
                    .ToList();
Exception message: 
Value cannot be null.
Parameter name: querySource
Stack trace:
   at Remotion.Utilities.ArgumentUtility.CheckNotNull[T](String argumentName, T actualValue)
   at Remotion.Linq.Clauses.Expressions.QuerySourceReferenceExpression..ctor(IQuerySource querySource)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.RewriteNavigationProperties(List`1 properties, IQuerySource querySource, Expression declaringExpression, String propertyName, Type propertyType, Func`2 propertyCreator, Func`2 conditionalAccessPropertyCreator)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.<>c__DisplayClass20_0.<VisitMember>b__0(IEnumerable`1 ps, IQuerySource qs)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.BindPropertyExpressionCore[TResult](Expression propertyExpression, IQuerySource querySource, Func`3 propertyBinder)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.BindNavigationPathPropertyExpression[TResult](Expression propertyExpression, Func`3 propertyBinder)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.VisitMember(MemberExpression node)
   at System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.VisitBinary(BinaryExpression node)
   at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Remotion.Linq.Clauses.WhereClause.TransformExpressions(Func`2 transformation)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ExpressionTransformingQueryModelVisitor`1.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.NavigationRewritingQueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
   at Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
   at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, 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)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult](QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](QueryModel queryModel)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](Expression query, INodeTypeProvider nodeTypeProvider, IDatabase database, ILogger logger, Type contextType)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass19_0`1.<CompileQuery>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.CompileQuery[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at Remotion.Linq.QueryableBase`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at EFTest.Program.Main(String[] args) in C:\Users\acherry\documents\visual studio 2015\Projects\EFTest\EFTest\Program.cs:line 65

Steps to reproduce

namespace EFTest
{
    public class LeafData
    {
        public int Id { get; set; }
    }

    public class NodeData
    {
        public int Id { get; set; }
        public LeafData Leaf { get; set; }
    }

    public class TestData : DbContext
    {
        public DbSet<NodeData> Nodes { get; set; }
        public TestData() : base()
        {
            
        }
        public TestData(DbContextOptions<TestData> options) : base(options)
        { }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlite("Filename=Sample.db");
            }
        }
    }

    public class ClientQueryObject
    {
        public NodeData Node { get; set; }
    }



    class Program
    {
        public static ClientQueryObject Create(NodeData node)
        {
            return new ClientQueryObject()
            {
                Node = node
            };
        }

        static void Main(string[] args)
        {
            using (var context = new TestData())
            {
                var results = context.Nodes.Include(node => node.Leaf)
                    .Select(node => Create(node))
                    .Where(clientquery => clientquery.Node.Leaf != null)
                    .ToList();
            }
        }
    }
}

Workaround: The issue with the expression compiler can be circumvented by modifying ClientQueryObject:

    public class ClientQueryObject
    {
        public NodeData Node { get; set; }
        public LeafData Leaf => Node.Leaf;
    }

and

                var results = context.Nodes.Include(node => node.Leaf)
                    .Select(node => Create(node))
                    .Where(clientquery => clientquery.Leaf != null)
                    .ToList();

Further technical details

EF Core version: 1.1.1, 1.1.0
Database Provider: SQLite
Operating system: Windows 10
IDE: VS 2015

@ajcvickers ajcvickers added this to the 2.0.0 milestone Mar 8, 2017
@pmiddleton
Copy link
Contributor

I just confirmed this is fixed in dev. I'm not sure which PR resolved the issue.

@ajcvickers ajcvickers modified the milestones: 2.0.0-preview1, 2.0.0 Apr 19, 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 Jun 27, 2017
@maumar
Copy link
Contributor

maumar commented Jun 27, 2017

also verified from my end, closing

@maumar maumar closed this as completed Jun 27, 2017
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