Concat different derived entities using OfType (TPH) throws exception
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
I would expect the following code to work, but it throws an exception.
See [the following gist](https://gist.github.com/joakimriedel/da8267bc9b461ef1701332d4c2a08912) for full repro.
```
Expression of type 'System.Linq.IQueryable`1[EfCoreBug.Program+Cat]' cannot be used for parameter of type 'System.Linq.IQueryable`1[EfCoreBug.Program+Dog]'
of method 'System.Linq.IQueryable`1[EfCoreBug.Program+Dog] Concat[Dog](System.Linq.IQueryable`1[EfCoreBug.Program+Dog], System.Collections.Generic.IEnumerable`1[EfCoreBug.Program+Dog])'
```
```C#
var userCatsAndAllDogs = await context.Users
.Where(u => u.Id == 1)
.SelectMany(m => m.Animals.OfType().Cast())
.Concat(
context.Animals.OfType().Cast()
)
.ToListAsync();
```
Also tried the following, but it does client eval and throws
```
Unable to translate set operation after client projection has been applied. Consider moving the set operation before the last 'Select' call.
```
```c#
var userCatsAndAllDogs = await context.Users
.Where(u => u.Id == 1)
.SelectMany(m => m.Animals.OfType().Select(c => c as Animal))
.Concat(
context.Animals.OfType().Select(d => d as Animal)
)
.ToListAsync();
```
This is a workaround, but I'd prefer using `OfType` if possible somehow?
```c#
var userCatsAndAllDogs = await context.Users
.Where(u => u.Id == 1)
.SelectMany(m => m.Animals.Where(a => EF.Property(a, "Discriminator") == "Cat"))
.Concat(
context.Animals.Where(a => EF.Property(a, "Discriminator") == "Dog")
)
.ToListAsync();
```
The resulting SQL query from workaround is the following, which I would have expected also from using `OfType`.
```sql
SELECT [t].[Id], [t].[Discriminator], [t].[UserId], [t].[NumberOfMiceKilled], [t].[IsShoeChewer]
FROM [Users] AS [u]
INNER JOIN (
SELECT [a].[Id], [a].[Discriminator], [a].[UserId], [a].[NumberOfMiceKilled], [a].[IsShoeChewer]
FROM [Animals] AS [a]
WHERE [a].[Discriminator] = N'Cat'
) AS [t] ON [u].[Id] = [t].[UserId]
WHERE [u].[Id] = 1
UNION ALL
SELECT [a0].[Id], [a0].[Discriminator], [a0].[UserId], [a0].[NumberOfMiceKilled], [a0].[IsShoeChewer]
FROM [Animals] AS [a0]
WHERE [a0].[Discriminator] = N'Dog'
```
### Include stack traces
```
An exception of type 'System.ArgumentException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Expression of type 'System.Linq.IQueryable`1[EfCoreBug.Program+Cat]' cannot be used for parameter of type 'System.Linq.IQueryable`1[EfCoreBug.Program+Dog]' of method 'System.Linq.IQueryable`1[EfCoreBug.Program+Dog] Concat[Dog](System.Linq.IQueryable`1[EfCoreBug.Program+Dog], System.Collections.Generic.IEnumerable`1[EfCoreBug.Program+Dog])''
at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)
at System.Linq.Expressions.Expression.Call(MethodInfo method, Expression arg0, Expression arg1)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessSetOperation(NavigationExpansionExpression outerSource, MethodInfo genericMethod, NavigationExpansionExpression innerSource)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.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__DisplayClass12_0`1.b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.d__65`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at EfCoreBug.Program.d__1.MoveNext()
```
### Include provider and version information
EF Core version: 6.0.3
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .net 6
Operating system: Win11
IDE: VS Code
Contributor guide
Assessment
This issue has not been assessed yet.