dotnet / dotnet/efcore

VB.Net Expression translation causes errors

Open
#31,878 2 comments 2 reactions 0 assignees View on GitHub
area-query customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

So we are converting an old project using EF6 to EF core. This project is written in VB.Net. After rewriting, we are running into issue with several queries. It turns out that expression trees in vb.net are sometimes built differently from expression trees in c#. But this causes issues with very basic queries.

Having 2 entities called `ParentEntity` and `ChildEntity` in which a one-to-many relation exists between them, we want to select a property of all child entities for a parent entity:

```vb.net
Dim test = dbContext.ParentEntities _
.Where(Function(x) x.ParentEntityId = 3) _
.SelectMany(Function(x) x.ChildEntities) _
.Select(Function(x) x.Text).ToArray()
```

this causes the error:
`The LINQ expression 'x => (IEnumerable)x.ChildEntities' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
`

with the following stacktrace:

Stacktrace
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessSelectMany(NavigationExpansionExpression source, LambdaExpression collectionSelector, LambdaExpression resultSelector)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryTranslationPreprocessor.Process(Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
at EfExpressionTest.Program.Main(String[] args) in C:\local projects\EfExpressionTest\Program.vb:line 12

This happens because the expression tree generated by vb.net contains a convert:

```
[Microsoft.EntityFrameworkCore.Query.EntityQueryRootExpression].Where(x => (x.ParentEntityId == 3)).SelectMany(x => Convert(x.ChildEntities, IEnumerable`1)).Select(x => x.Text)
```

while the c# variant does not:

```
[Microsoft.EntityFrameworkCore.Query.EntityQueryRootExpression].Where(x => (x.ParentEntityId == 3)).SelectMany(x => x.ChildEntities).Select(x => x.Text)
```

I've attached a sample project demonstrating the issue.
[ReproductionScenario.zip](https://github.com/dotnet/efcore/files/12739348/ReproductionScenario.zip)

Now I already found #20390 which describes a similar situation, and there it was suggested to create a strongly typed call (https://github.com/dotnet/efcore/issues/20390#issuecomment-605342170) but in this situation I don't think we have any influence on how the call is done.

If you guys deem this to be not a bug, I'd like to know what we are doing wrong here. We have a lot of queries that used to work fine in ef6 with vb.net, that break after converting it to EF core. Ideally, we would like a fix for this in ef core 3, since the project we are migrating is written in .net framework, and a conversion to .net core is far away.

### Include provider and version information

EF Core version: Both with 7.0.11 and 3.1.32
Database provider: Irrelevant I think, but happens with both sqlserver and inmemory
Target framework: both with .net framework and .net 7
Operating system: windows
IDE: . Visual Studio 2022 17.7.4

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.