Efcore: InMemory: When adding subquery projection, take into account client projection

Created on 4 Sep 2019  路  10Comments  路  Source: dotnet/efcore

area-in-memory area-query punted-for-3.1 type-bug

Most helpful comment

Really keen to hear if there is an ETA for this. It's a blocker for our migration to 3.1 at this point.

All 10 comments

So how exactly are we supposed to work around this? Using an anonymous object doesn't work either, and we can't create tuples in expressions?

We are just now attempting to update to dotnet 3 (from 2.2), and we have a bunch of failing tests because of this..

any update on this?

I'm getting this exact error, but in a different, quite specific, situation.

Scenario: Fetching a Parent-ChildCollection and projecting to new Parent-ChildAggregate with a nested Parent.OwnedEntityProperty.

Json representation of source Parent entity structure:
{ "Config": { "SubConfig": { } } "Child": [] }

Whenever I try aggregate the child list AND retrieve the nested value object, I get the Unable to cast object of type 'System.Linq.Expressions.NewExpression' to type 'System.Linq.Expressions.MethodCallExpression' error.

I created a simple console app and proved that this is the only scenario it happens in.

  • No child aggregate, just nested config -> passes
  • Just child aggregate, no config -> passes
  • Child Aggregate, with non-nested config -> passes
  • Child list, with nested config -> passes
  • Child aggregate, with nested config -> FAILS

In my real project the last scenario succeeds against SQL Server, I have not tried this sample against SQL.

EFCoreTests.zip

To work around this I am checking if the Db is in memory, then split the query into 2. That way my tests pass, and I still have the performance of a single read to the real Db.

Really keen to hear if there is an ETA for this. It's a blocker for our migration to 3.1 at this point.

For anyone coming across this because they're trying to use a .Count alongside a parameterized constructor (like my issue https://github.com/dotnet/efcore/issues/21001 ), we've worked around this by wrapping the Count in a Convert.ToInt32 call. This fixes the tests that use the InMemory provider. In terms of the SQL generated for the SQL Server provider, this adds a CONVERT. Someone who is more of an expert on SQL perf can correct me if I'm wrong, but I don't think that should adversely affect performance, and for us it's superior to dropping to parameterless ctors.

@PoyaManouchehri don't know if this helps you?

I have this exception used Select and Count together.

var test = await db.Users.Select(u => new
                {
                    u.Id,
                    Acts = u.Activities.Select(a => new { a.Id }),
                    ActsCount = u.Activities.Count(),
                }).ToListAsync();

@jgbpercy I can confirm that our original issue (exception when using .Any() in a subquery) is fixed in EF Core InMemory 3.1.6.

.Any() is still a problem for me in EF Core InMemory 3.1.7. When I replace .any() with .Count() > 0 my tests pass.

This still fails in 3.1.8 in InMemoryDatabase but works fine in SQL Server/PostgreSQL.

Exception

Unable to cast object of type 'System.Linq.Expressions.NewExpression' to type 'System.Linq.Expressions.MethodCallExpression'.

code
```c#
public static IQueryable ToDtoList(this IQueryable data)
{
return data.Select(AsDto);
}

public static readonly Expression> AsDto =
item => new ContainerDto
{
Text = item.Text,
Cars = item.Cars
.AsQueryable()
.Select(AsCarDto)
.FirstOrDefault(),
};

public static readonly Expression> AsCarDto =
item => new CarDto
{
Name = item.Name,
};
```

I am having the same problem as reply above. Works in SQL Server but not InMemoryDatabase. Is there a known workaround?

Thanks!

Was this page helpful?
0 / 5 - 0 ratings