Efcore: Query: UseInMemoryDatabase throw KeyNotFoundException when invoke include function

Created on 9 Apr 2018  路  6Comments  路  Source: dotnet/efcore

When the Include method is called,use "_" as the variable name in the lambda expression , throws KeyNotFoundException.

```c#
Exception message:
KeyNotFoundException: The given key was not present in the dictionary.
Stack trace:
System.ThrowHelper.ThrowKeyNotFoundException()
System.Collections.Generic.Dictionary.get_Item(TKey key)
Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.DefaultQueryExpressionVisitor.GetParameterValue(QueryContext queryContext, string parameterName)
lambda_method(Closure , AnonymousObject )
System.Linq.Lookup.CreateForJoin(IEnumerable source, Func keySelector, IEqualityComparer comparer)
System.Linq.Enumerable+d__81.MoveNext()
System.Collections.Generic.EnumerableHelpers.ToArray(IEnumerable source, out int length)
System.Linq.Buffer..ctor(IEnumerable source)
System.Linq.OrderedEnumerable+d__3.MoveNext()
System.Linq.Enumerable+SelectIPartitionIterator.MoveNext()
Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.IncludeCollection(int includeId, INavigation navigation, INavigation inverseNavigation, IEntityType targetEntityType, IClrCollectionAccessor clrCollectionAccessor, IClrPropertySetter inverseClrPropertySetter, bool tracking, TEntity entity, Func> relatedEntitiesFactory, Func joinPredicate)
lambda_method(Closure , QueryContext , Ticket , Object[] )
Microsoft.EntityFrameworkCore.Query.Internal.IncludeCompiler._Include(QueryContext queryContext, TEntity entity, Object[] included, Action lambda_method(Closure , Ticket )
System.Linq.Enumerable+SelectIPartitionIterator.MoveNext()
Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider+<_TrackEntities>d__17.MoveNext()
Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider+ExceptionInterceptor+EnumeratorExceptionInterceptor.MoveNext()
System.Linq.AsyncEnumerable+AsyncEnumerableAdapter.MoveNextCore(CancellationToken cancellationToken)
System.Linq.AsyncEnumerable+AsyncIterator+d__10.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult()
System.Collections.Generic.AsyncEnumerableHelpers+d__1.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult()
System.Collections.Generic.AsyncEnumerableHelpers+d__0.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
InMemoryDatabase.Controllers.ValuesController+d__3.MoveNext() in ValuesController.cs
+
var result = await this._appDbContext.Set().Include(_ => _.Items).ToArrayAsync();
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+d__12.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+d__10.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+d__14.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+d__17.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+d__15.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+d__7.MoveNext()


### Steps to reproduce
```c#
namespace InMemoryDatabase
{
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Infrastructure;
    using Microsoft.EntityFrameworkCore.Infrastructure.Internal;

    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options)
            : base(options)
        {
        }

        public CoreOptionsExtension CoreOptions { get; set; }

        public InMemoryOptionsExtension InMemoryOptions { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Ticket>().ToTable("Ticket").HasMany(_ => _.Items).WithOne(_ => _.Ticket)
                .HasForeignKey(_ => _.TicketId).OnDelete(DeleteBehavior.Cascade);

            modelBuilder.Entity<TicketItem>().ToTable("TicketItem");
        }
    }

 public class Ticket
    {
        public long Id { get; set; }

        public IEnumerable<TicketItem> Items { get; set; }
    }

 public class TicketItem
    {
        public long Id { get; set; }

        public long TicketId { get; set; }

        public Ticket Ticket { get; set; }
    }
}

```c#
public class Startup
{

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddEntityFrameworkInMemoryDatabase();
        services.AddDbContext<AppDbContext>(
            opts => { opts.UseInMemoryDatabase("app-db-context"); });
    }
}

## Throw KeyNotFoundException
```c#
 this._appDbContext.Set<Ticket>().Add(new Ticket { Items = new[] { new TicketItem() } });
            await this._appDbContext.SaveChangesAsync();

            // OK
            var result = await this._appDbContext.Set<Ticket>().Include(t => t.Items).ToArrayAsync();

            // Throw KeyNotFoundException 
            result = await this._appDbContext.Set<Ticket>().Include(_ => _.Items).ToArrayAsync();

Further technical details

EF Core version: 2.1.0-preview1-final
Database Provider: Microsoft.EntityFrameworkCore.InMemory
Operating system: Win 10
IDE: Visual Studio 2017 15.6.5

area-query closed-fixed type-bug

Most helpful comment

Putting on the backlog. Workaround is to not use "_".

All 6 comments

Same happens with correlated subquery too.

This line causes https://github.com/aspnet/EntityFrameworkCore/blob/0e1d2ca3d7b4dc49b77368ede5ccb8b26a4fa1f3/src/EFCore/Query/Internal/IncludeCompiler.CollectionQueryModelRewritingExpressionVisitor.cs#L384

querySource item name to be __ which is reserved prefix for parameters in QCC.

Putting on the backlog. Workaround is to not use "_".

That's a weird bug... I wouldn't have expected the name of the lambda parameter to have any effect. Will this be fixed for 3.0?

@thomaslevesque This issue is in the Backlog milestone. This means that it is not going to happen for the 3.0 release. We will re-assess the backlog following the 3.0 release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

@ajcvickers sure, I understand. It's not a very big issue anyway, and there's an easy workaround.

This is working in 3.1

Was this page helpful?
0 / 5 - 0 ratings