Search code examples
c#asp.net-corelinq2db

linq2db throws exception when filtering by nested collection


We are using .NET Core 3.1, Microsoft.EntityFrameworkCore 3.1.9, Npgsql 4.1.9 and linq2db.EntityFrameworkCore 3.7.0.

We have the following 2 scaffolded classes:

[Table("testrunconfig", Schema = "fit")]
public partial class Testrunconfig
{
    public Testrunconfig()
    {
        Testruntestgrp = new HashSet<Testruntestgrp>();
    }
    
    [Key]
    [Column("id")]
    public int Id { get; set; }
    
    [InverseProperty("Testrunconfig")]
    public virtual ICollection<Testruntestgrp> Testruntestgrp { get; set; }
}

[Table("testruntestgrp", Schema = "fit")]
public partial class Testruntestgrp
{
    [Key]
    [Column("id")]
    public int Id { get; set; }

    [ForeignKey(nameof(TestrunconfigId))]
    [InverseProperty("Testruntestgrp")]
    public virtual Testrunconfig Testrunconfig { get; set; }
}

When I try to execute the following query ...

var testName = "MyTestName"
var test = _fitDbContext.Testrunconfig
    .Include(x => x.Testruntestgrp)
    .Where(x => x.Testruntestgrp.Select(y => y.Testname).Contains("MyTestName"))
    .Take(10)
    .ToListAsyncLinqToDB()
    .Result;

... this exception is thrown:

Exception thrown: 'LinqToDB.Linq.LinqException' in linq2db.dll
Exception thrown: 'LinqToDB.Linq.LinqException' in linq2db.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Executed action MyProject.Web.Controllers.TestExecutions.TestExecutionsController.IndexAlternate (MyProject.Web) in 7928.1909ms
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint 'MyProject.Web.Controllers.TestExecutions.TestExecutionsController.IndexAlternate (MyProject.Web)'
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
'iisexpress.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.32\System.Diagnostics.StackTrace.dll'. 
'iisexpress.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.32\System.Reflection.Metadata.dll'. 
'iisexpress.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.32\System.IO.MemoryMappedFiles.dll'. 
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request.

System.AggregateException: One or more errors occurred. (One or more errors occurred. ('x.Testruntestgrp.Select(y => y.Testname).Contains(value(MyProject.Service.TestExecutionsService+<>c__DisplayClass3_0).testName)' cannot be converted to SQL.))
 ---> System.AggregateException: One or more errors occurred. ('x.Testruntestgrp.Select(y => y.Testname).Contains(value(MyProject.Service.TestExecutionsService+<>c__DisplayClass3_0).testName)' cannot be converted to SQL.)
 ---> LinqToDB.Linq.LinqException: 'x.Testruntestgrp.Select(y => y.Testname).Contains(value(MyProject.Service.TestExecutionsService+<>c__DisplayClass3_0).testName)' cannot be converted to SQL.
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertInPredicate(IBuildContext context, MethodCallExpression expression)
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertPredicate(IBuildContext context, Expression expression)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSearchCondition(IBuildContext context, Expression expression, List`1 conditions, Boolean isNotExpression)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildWhere(IBuildContext parent, IBuildContext sequence, LambdaExpression condition, Boolean checkForSubQuery, Boolean enforceHaving)
   at LinqToDB.Linq.Builder.WhereBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.TakeSkipBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.Build[T]()
   at LinqToDB.Linq.Query`1.CreateQuery(IDataContext dataContext, Expression expr)
   at LinqToDB.Linq.Query`1.GetQuery(IDataContext dataContext, Expression& expr)
   at LinqToDB.Linq.ExpressionQuery`1.GetQuery(Expression& expression, Boolean cache)
   at LinqToDB.Linq.ExpressionQuery`1.LinqToDB.Async.IQueryProviderAsync.ExecuteAsyncEnumerable[TResult](Expression expression, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at LinqToDB.EntityFrameworkCore.Internal.LinqToDBForEFQueryProvider`1.GetAsyncEnumerator(CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at LinqToDB.AsyncExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken token)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at MyProject.Service.TestExecutionsService.GetTestBisectedExecutions(String configuration, Int32 maxTransitions, String testName, String svnRevision) in E:\MyDevCheckouts\DevFolder\MyProject_trunk\MyProject.Service\TestExecutionsService.cs:line 56
   at MyProject.Web.Controllers.TestExecutions.TestExecutionsController.IndexAlternate(BisectExecutionsGuiModel model) in E:\MyDevCheckouts\DevFolder\MyProject_trunk\MyProject.web\Controllers\TestExecutions\TestExecutionsController.cs:line 98
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
   at DevExpress.AspNetCore.Internal.BinaryStorageMiddleware.Invoke(HttpContext httpContext)
   at DevExpress.AspNetCore.Internal.ResourceManagerMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Exception thrown: 'System.NotImplementedException' in System.Private.CoreLib.dll
Exception thrown: 'System.NotImplementedException' in System.Private.CoreLib.dll

What am I doing wrong? This seems such a basic use-case. It works in EF Core 3.1.


Solution

  • This filter construction is not supported. Try to change it to Any. Also do not mix async conde with sync.

    var test = _fitDbContext.Testrunconfig
        .Include(x => x.Testruntestgrp)
        .Where(x => x.Testruntestgrp.Any(y => y.Testname == "MyTestName")
        .Take(10)
        .ToLinqToDB() 
        .ToList()