Efcore: An new ArgumentException is throw(already catched) with Navigation Property in EFCore2.1?

Created on 21 Apr 2018  路  25Comments  路  Source: dotnet/efcore

Describe what is not working as expected.

An new ArgumentException is throw as FirstChanceException(already catched in EntityQueryModelVisitor.ShiftMemberAccess) in EFCore2.1-preview2, and that never happened in EFCore2.0. Is this behavior work as excepted?
Seems not affact the result and not break program, but it's annoying when debug program or do log with FirstChanceException.

BTW(may not related to the issue):
Since QuerySourceMapping.RemoveMapping is available now in Relinq, should it be used somewhere, according to the comment in the catch in ShiftMemberAccess if it's really stale?

If you are seeing an exception, include the full exceptions details (message and stack trace).

Exception message: System.ArgumentException: Field 'Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor+TransparentIdentifier`2[AAA,System.Collections.Generic.IEnumerable`1[BBB]].Inner' is not defined for type 'Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor+TransparentIdentifier`2[AAA,BBB]'
Stack trace:

   at System.Linq.Expressions.Expression.Field(Expression expression, FieldInfo field)
   at System.Environment.get_StackTrace()
   at ConsoleApp15.Program.<>c.<Main>b__0_0(Object sender, FirstChanceExceptionEventArgs ev) in c:\users\yyjde_000\documents\visual studio 2017\Projects\ConsoleApp15\ConsoleApp15\Program.cs:line 11
   at System.Linq.Expressions.Expression.Field(Expression expression, FieldInfo field)
   at System.Linq.Expressions.Expression.MakeMemberAccess(Expression expression, MemberInfo member)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.ShiftMemberAccess(Expression targetExpression, Expression currentExpression)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.IntroduceTransparentScope(IQuerySource querySource, QueryModel queryModel, Int32 index, Type transparentIdentifierType)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitGroupJoinClause(GroupJoinClause groupJoinClause, QueryModel queryModel, Int32 index)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitGroupJoinClause(GroupJoinClause groupJoinClause, 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.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult](QueryModel queryModel)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](Expression query, IQueryModelGenerator queryModelGenerator, IDatabase database, IDiagnosticsLogger`1 logger, Type contextType)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass13_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Remotion.Linq.QueryableBase`1.GetEnumerator()
   at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

Steps to reproduce

Include a complete code listing (or project/solution) that we can run to reproduce the issue.

Partial code listings, or multiple fragments of code, will slow down our response or cause us to push the issue back to you to provide code to reproduce the issue.

```c#
AppDomain.CurrentDomain.FirstChanceException += (sender, ev) => Console.WriteLine(ev.Exception + Environment.NewLine + Environment.StackTrace);
using (var ctx = new TestContext())
{
//EntityQueryModelVisitor.TransparentIdentifier> vs
//EntityQueryModelVisitor.TransparentIdentifier
var a = ctx.Device
.Include(d => d.Type1)
.Include(d => d.Type2)
.ToList();

            //See difference after remove DictType1/DictType2(Type) or `DefaultIfEmpty()` or both
            var a2 = (from Device d in ctx.Device
                      join DictType2 t2 in ctx.DictType2 on d.Type2Id equals t2.Type2Id into t2g
                      from DictType2 t2 in t2g.DefaultIfEmpty()
                      join DictType1 t1 in ctx.DictType1 on d.Type1Id equals t1.Type1Id into t1g
                      from DictType1 t1 in t1g.DefaultIfEmpty()
                      select new { d, t1, t2 }).ToList();

            var b = ctx.Device
                .Include(d => d.Type1)
                .Where(d => d.Group.Status == 0)
                .ToList();

            //Exception Message with different Type
            //EntityQueryModelVisitor.TransparentIdentifier<ValueBuffer,IEnumerable<ValueBuffer>> vs 
            //EntityQueryModelVisitor.TransparentIdentifier<EntityQueryModelVisitor.TransparentIdentifier<ValueBuffer,ValueBuffer>,ValueBuffer>
            var c = ctx.Device
                .Select(d=>new
                {
                    d.DeviceId,
                    Type1Name = d.Type1.Type1Name,
                    NameA = d.RawANavigation.Raw2.Raw2Name,
                })
                .ToList();
        }
The table struct like this
```c#
    public partial class Device
    {
        public int DeviceId { get; set; }
        public int? Type1Id { get; set; }
        public int? Type2Id { get; set; }
        public int GroupId { get; set; }
        public int? RawA { get; set; }
        public int? RawB { get; set; }
        public int? RawC { get; set; }

        public Group Group { get; set; }
        public Raw RawANavigation { get; set; }
        public Raw RawBNavigation { get; set; }
        public Raw RawCNavigation { get; set; }
        public DictType1 Type1 { get; set; }
        public DictType2 Type2 { get; set; }
    }
    public partial class DictType1
    {
        public DictType1()
        {
            Device = new HashSet<Device>();
            DictType2 = new HashSet<DictType2>();
        }

        public int Type1Id { get; set; }
        public string Type1Name { get; set; }

        public ICollection<Device> Device { get; set; }
        public ICollection<DictType2> DictType2 { get; set; }
    }
    public partial class DictType2
    {
        public DictType2()
        {
            Device = new HashSet<Device>();
        }

        public int Type2Id { get; set; }
        public string Type2Name { get; set; }
        public int? Type1Id { get; set; }

        public DictType1 Type1 { get; set; }
        public ICollection<Device> Device { get; set; }
    }
    public partial class Group
    {
        public Group()
        {
            Device = new HashSet<Device>();
        }

        public int GroupId { get; set; }
        public byte Status { get; set; }

        public ICollection<Device> Device { get; set; }
    }
    public partial class Raw
    {
        public Raw()
        {
            DeviceRawANavigation = new HashSet<Device>();
            DeviceRawBNavigation = new HashSet<Device>();
            DeviceRawCNavigation = new HashSet<Device>();
        }

        public int RawId { get; set; }
        public int? Raw2Id { get; set; }

        public Raw2 Raw2 { get; set; }
        public ICollection<Device> DeviceRawANavigation { get; set; }
        public ICollection<Device> DeviceRawBNavigation { get; set; }
        public ICollection<Device> DeviceRawCNavigation { get; set; }
    }
    public partial class Raw2
    {
        public Raw2()
        {
            Raw = new HashSet<Raw>();
        }

        public int Raw2Id { get; set; }
        public string Raw2Name { get; set; }

        public ICollection<Raw> Raw { get; set; }
    }

Further technical details

EF Core version: 2.1.0-preview1-final/2.1.0-preview2-final/2.1.0-rc1-30631(from myget/aspnetcore-dev)
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Win10 x64 17650 Insider Preview
IDE: Visual Studio 2017 15.7.0preview4

closed-fixed type-cleanup

Most helpful comment

Since multiple people are commenting on this I want to clarify the situation. We would love to fix this now, but the problem is that the exception is thrown by a third-party dependency, and the try-catch in the EF code is a workaround for that exception. We are removing that dependency in 3.0 and hence this will no longer be an issue. Now obviously if this was causing many people's running apps to fail, then we would have to look into doing something more drastic sooner. However, that's not the case with this issue. It's only a problem in some scenarios when using the debugger, and there are workarounds even for that. It's unfortunate that this is resulting in a bad experience for some people when debugging and I wish that wasn't the case, but in the grand scheme of things this still doesn't feel like a critical issue that must be patched before 3.0.

All 25 comments

Maybe related to #7973? But this only happen with efcore2.1.

Note for triage: the code in question:
```C#
private static Expression ShiftMemberAccess(Expression targetExpression, Expression currentExpression)
{
if (!(currentExpression is MemberExpression memberExpression))
{
return targetExpression;
}

try
{
    return Expression.MakeMemberAccess(
        ShiftMemberAccess(targetExpression, memberExpression.Expression),
        memberExpression.Member);
}
catch (ArgumentException)
{
    // Member is not defined on the new target expression.
    // This is due to stale QuerySourceMappings, which we can't
    // remove due to there not being an API on QuerySourceMapping.
}

return currentExpression;

}
```

Triage: note this may not be needed depending on outcome of #12048

Just for clarification since #12548 got closed. Is this issue here really scheduled for version 3.0?

At least in my case version 2.1 is completely unusable until this issue is solved.

Is it related to some special configuration? We're not even using inheritance, it is just loading nested objects. The only "special" thing we have is that some of these nested objects are in a 1:1 relationship.

@leak - Yes this issue is planned to be fixed in 3.0 release.
The reason it is not high priority issue because it is first chance exception which is already caught.

Well it is great that these exceptions are caught, the problem is there are _way_ too many of them and apparently they seem to grow exponentially when loading more nested objects.

When I start my application and call the API for the first time I have to wait 40 seconds (in words: forty seconds) for all the exceptions to scroll by in the Debug window before I can do anything at all.

Wasn't there some concern about improving developers "inner loop"? This completely breaks it for me.
I'm also wondering why there are so few people with this kind of problem. Is nobody loading nested objects...?

I really wish this would gain more attention as it still is a complete blocker for me.

@leak - Change your debugger settings in VS to Enable Just My Code then you won't see these exceptions in debug window.

This does hide the issue yes, not my preferred way of development though.

I have this issue too and as @leak I can't use EntityFramework 2.1. I can't understand why this isn't a high priority bug...

I am having this issue as well and it is causing minutes of lag for a single query, one that only took a second previously.

I am having this issue too. This cause two major issues: A very slow execution time and in my other scenario, where I use EF together with an OData Query, the execution is canceled and no data is loaded.

Please schedule this bug with higher priority! In my case I am not able to use EF 2.1 with this behavior.

@Shadetheartist @Shadetheartist @smartcodinghub If this slow down is happening outside of the debugger, then please file a new issue with a runnable project/solution or code listing that demonstrates the behavior.

It's only occurring when debugging. But that's not a valid reason to not fix this with more urgency. I use Jetbrains Rider instead of Visual Studio, and i can't find a 'Just my Code' setting in that IDE, so have to run without debugging to actually use my app. This proves to be a pretty prohibitive to speedy and effective development. In my estimation it's not appropriate to wait to fix this this until 3.0, it should be hotfixed as soon as possible.

Thank the good lord Jesus Christ i avoided EF in my other projects. Abstinence is a virtue i guess.

Hi,
I have the same issue and it is very annoying when we have not the enable just my code. This option is needed to report bugs in third party libs (like WebApi ODate).

I hope this will be fixed before 3.0.

Regards,
J茅r么me

I'm having this issue as well.

Seems not happen on 2.2.0-preview3, not sure whether it's fixed.

Getting this as well on 2.1.4, still an issue on the very latest prerelease builds too.

Only shows up when Common Language Runtime Exceptions is ticked in VS Exception Settings

Minimal repo here: https://github.com/MattJeanes/EFCore-Sqlite-JoinIssue

The error I'm getting:

System.ArgumentException: 'Field 'Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor+TransparentIdentifier`2[EFCore_Sqlite_JoinIssue.Ticket,System.Collections.Generic.IAsyncEnumerable`1[EFCore_Sqlite_JoinIssue.User]].Inner' is not defined for type 'Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor+TransparentIdentifier`2[EFCore_Sqlite_JoinIssue.Ticket,EFCore_Sqlite_JoinIssue.User]''

I'm having this issue as well.

Hi
we have also this issue, I hope this will fixed recently and we have not waiting for 3.0

I have the same issue with v.2.1

Since multiple people are commenting on this I want to clarify the situation. We would love to fix this now, but the problem is that the exception is thrown by a third-party dependency, and the try-catch in the EF code is a workaround for that exception. We are removing that dependency in 3.0 and hence this will no longer be an issue. Now obviously if this was causing many people's running apps to fail, then we would have to look into doing something more drastic sooner. However, that's not the case with this issue. It's only a problem in some scenarios when using the debugger, and there are workarounds even for that. It's unfortunate that this is resulting in a bad experience for some people when debugging and I wish that wasn't the case, but in the grand scheme of things this still doesn't feel like a critical issue that must be patched before 3.0.

Since multiple people are commenting on this I want to clarify the situation. We would love to fix this now, but the problem is that the exception is thrown by a third-party dependency, and the try-catch in the EF code is a workaround for that exception. We are removing that dependency in 3.0 and hence this will no longer be an issue. Now obviously if this was causing many people's running apps to fail, then we would have to look into doing something more drastic sooner. However, that's not the case with this issue. It's only a problem in some scenarios when using the debugger, and there are workarounds even for that. It's unfortunate that this is resulting in a bad experience for some people when debugging and I wish that wasn't the case, but in the grand scheme of things this still doesn't feel like a critical issue that must be patched before 3.0.

Ok fair enough

We no longer have offending code in codebase.

Was this page helpful?
0 / 5 - 0 ratings