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

EF 7 LINQ query with .Select() including collection throws ArgumentNullException when .Take() is used #3804

Closed
jemiller0 opened this issue Nov 19, 2015 · 9 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

@jemiller0
Copy link

I found that the query below throws an ArgumentNullException when used with EF 7 RC 1. It works in EF 6. If you comment out the .Take(100), the query works. Also, it doesn't matter if there are any rows in the database. Initially, I was using .FirstOrDefault() which has the same problem, but, I found that the problem even occurs if you use .Any().

using Microsoft.Data.Entity;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var bc = new BlogContext())
            {
                bc.Database.EnsureCreated();
                for (int i = 0; i < 5; i++)
                {
                    var b = new Blog { };
                    bc.Blogs.Add(b);
                    var p = new Post { Blog = b };
                    bc.Posts.Add(p);
                }
                bc.SaveChanges();
                bc.Blogs
                    .Take(100)
                    //.Select(b2 => b2.Posts.Any())
                    .Select(b2 => b2.Posts.FirstOrDefault().Content)
                    .ToArray();
            }
        }
    }

    public class BlogContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Blogs;Trusted_Connection=True;");
    }

    public class Blog
    {
        public int? Id { get; set; }
        public ICollection<Post> Posts { get; set; }
    }

    public class Post
    {
        public int? Id { get; set; }
        public string Content { get; set; }
        public int? BlogId { get; set; }
        public Blog Blog { get; set; }
    }
}
@rowanmiller
Copy link
Contributor

Appears to be the same code as #3807 but one reports bad SQL and the other an exception

@jemiller0
Copy link
Author

Yes, the code is almost the same. Basically, if you have a Take(), it fails with an exception. If you comment that out, it works, however, the generated SQL looks wrong. It works, but, it would be very inefficient if the table had a large number or rows since it isn’t filtering and is querying for the entire table (the subqueries).

@rowanmiller
Copy link
Contributor

Ok I see now that your comments mention that commenting out the Take makes it work. We were just skimming you repro code and the Take is commented out - so we assumed you saw the error with the code listing provided. I updated the listing to be the code that reproduces the issue.

@jemiller0
Copy link
Author

OK, thanks.

@creeve
Copy link

creeve commented Dec 1, 2015

I found that calling .Take() before .Select() throws a TargetInvocationException, while calling Take after Select works seemingly correctly. The ordering of these wasn't a problem in EF 6. I don't know why my exception is different from jemiller0's because it seems like I encountered the exact same problem.

I'm also on EF 7 RC 1.

@ghost
Copy link

ghost commented Feb 21, 2016

Hello,

I am working on large scale project with my team and we have started using EF7. We have encountered the same bug as creeve TargetInvocationException. I was wondering is there any quick fix or should we go back to EF6?

@robertledinski
Copy link

Just found some workaround. First use select, then .AsQuerayable().Skip().Take().ToList(). That should do the trick. Works for me.

@koenbeuk
Copy link

Same problem here (latest RC1 bits), @robertledinski workaround indeed does the trick. Note that the issue can also be reproduced when using simple navigation properties. My reproduction:

    public class Foo {
        public int Id { get; set; }
        public Bar Bar { get; set; }
    }
    public class Bar {
        public int Id { get; set; }
        public string Test { get; set; }
    }
    public class AppContext : DbContext    {
        public DbSet<Foo> Foo { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder o) => o.UseSqlServer("...");
    }

    void Test()
    {
        using (var c = new AppContext())
        {
            var r = c.Foo
                .Take(1) // this will cause an exception
                .Skip(1) // this will also cause an exception
                .Select(x => x.Bar.Test) // when selecting a property of a relation that is not part of the foreign key
                //.Select(x => x.Bar.Id) // but not if selecting the primary key instead
                .ToList();
        }
    }

exception stacktrace:
{System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentNullException: Value cannot be null. Parameter name: provider at Microsoft.Data.Entity.Utilities.Check.NotNull[T](T value, String parameterName) at Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor._CreateEntityQueryable[TResult](IAsyncQueryProvider entityQueryProvider) --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.CreateEntityQueryable(IEntityType targetEntityType) at Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.CreateJoinsForNavigations(QuerySourceReferenceExpression outerQuerySourceReferenceExpression, IEnumerable1 navigations)
at Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.<>c__DisplayClass13_0.b__0(IEnumerable1 ps, IQuerySource qs) at Microsoft.Data.Entity.Query.EntityQueryModelVisitor.BindMemberExpressionCore[TResult](MemberExpression memberExpression, IQuerySource querySource, Func3 memberBinder)
at Microsoft.Data.Entity.Query.EntityQueryModelVisitor.BindNavigationPathMemberExpression[TResult](MemberExpression memberExpression, Func3 memberBinder) at Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.VisitMember(MemberExpression memberExpression) at System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node) at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node) at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection1 nodes, Func2 elementVisitor) at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node) at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at Remotion.Linq.Clauses.SelectClause.TransformExpressions(Func2 transformation)
at Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.NavigationRewritingQueryModelVisitor.VisitSelectClause(SelectClause selectClause, QueryModel queryModel)
at Remotion.Linq.Clauses.SelectClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel)
at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
at Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.NavigationRewritingExpressionVisitor.Rewrite(QueryModel queryModel)
at Microsoft.Data.Entity.Query.EntityQueryModelVisitor.OptimizeQueryModel(QueryModel queryModel)
at Microsoft.Data.Entity.Query.EntityQueryModelVisitor.CreateAsyncQueryExecutor[TResult](QueryModel queryModel)
at Microsoft.Data.Entity.Storage.Database.CompileAsyncQuery[TResult](QueryModel queryModel)
at Microsoft.Data.Entity.Query.Internal.QueryCompiler.<>c__DisplayClass19_01.<CompileAsyncQuery>b__0() at Microsoft.Data.Entity.Query.Internal.CompiledQueryCache.GetOrAddAsyncQuery[TResult](Object cacheKey, Func1 compiler)
at Microsoft.Data.Entity.Query.Internal.QueryCompiler.CompileAsyncQuery[TResult](Expression query)
at Microsoft.Data.Entity.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query)
at Microsoft.Data.Entity.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression)
at Microsoft.Data.Entity.Query.Internal.EntityQueryable1.System.Collections.Generic.IAsyncEnumerable<TResult>.GetEnumerator() at System.Linq.AsyncEnumerable.Aggregate[TSource,TAccumulate,TResult](IAsyncEnumerable1 source, TAccumulate seed, Func3 accumulator, Func2 resultSelector, CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.Aggregate[TSource,TAccumulate](IAsyncEnumerable1 source, TAccumulate seed, Func3 accumulator, CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.ToList[TSource](IAsyncEnumerable1 source, CancellationToken cancellationToken) at Microsoft.Data.Entity.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable1 source, CancellationToken cancellationToken)
at ...UserCode...`

@mikary mikary assigned mikary and unassigned anpete Apr 27, 2016
@mikary
Copy link
Contributor

mikary commented Apr 27, 2016

Verified that this issue reproduces in EntityFramework.MicrosoftSqlServer 7.0.0-RC1-final but it does not throw the exception in the current dev branch.

@rowanmiller rowanmiller modified the milestones: 1.0.0-rc2, 1.0.0 May 4, 2016
mikary added a commit that referenced this issue May 17, 2016
Add test for #3804 - Select Navigation following Skip or Take
Add test for #3674 - GroupBy with Where on Navigation Property
Add test for #3676 - GroupBy Let on Navigation Property (disabled)
Add test for #3913 - Sum + Count inside Select
mikary added a commit that referenced this issue May 17, 2016
Add test for #3804 - Select Navigation following Skip or Take
Add test for #3674 - GroupBy with Where on Navigation Property
Add test for #3676 - GroupBy Let on Navigation Property (disabled)
Add test for #3913 - Sum + Count inside Select
@ajcvickers ajcvickers removed this from the 1.0.0-rc2 milestone Oct 15, 2022
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Oct 15, 2022
@ajcvickers ajcvickers added this to the 1.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

8 participants