Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filtering using Contains throws UnreachableException #41

Open
rt-tidaro opened this issue Apr 23, 2024 · 7 comments
Open

Filtering using Contains throws UnreachableException #41

rt-tidaro opened this issue Apr 23, 2024 · 7 comments

Comments

@rt-tidaro
Copy link

Hello,

First of all, great library. Thanks for all your hard work!

After updating EF Core from 7.x to 8.04. and this library from 7.x to 8.0.1, I've encountered an error when trying to filter on LocalDate properties using Contains:

var dates = new[]
{
    new LocalDate(2024, 04, 22),
    new LocalDate(2024, 04, 23)
};

var results = dbContext.SomeEntities
    .Where(someEntity => dates.Contains(someEntity.LocalDate))
    .ToArrayAsync();

The above code will throw the following exception:

System.Diagnostics.UnreachableException : A SqlServerStringTypeMapping collection type mapping could not be found
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQueryableMethodTranslatingExpressionVisitor.SqlServerInferredTypeMappingApplier.ApplyTypeMappingsOnOpenJsonExpression(SqlServerOpenJsonExpression openJsonExpression, IReadOnlyList`1 typeMappings)
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQueryableMethodTranslatingExpressionVisitor.SqlServerInferredTypeMappingApplier.VisitExtension(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.<VisitChildren>g__VisitList|128_0[T](List`1 list, Boolean inPlace, Boolean& changed, <>c__DisplayClass128_0&)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.VisitChildren(ExpressionVisitor visitor, Boolean updateColumns)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.VisitChildren(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.RelationalInferredTypeMappingApplier.VisitExtension(Expression expression)
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQueryableMethodTranslatingExpressionVisitor.SqlServerInferredTypeMappingApplier.VisitExtension(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.InExpression.VisitChildren(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.RelationalInferredTypeMappingApplier.VisitExtension(Expression expression)
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQueryableMethodTranslatingExpressionVisitor.SqlServerInferredTypeMappingApplier.VisitExtension(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.VisitChildren(ExpressionVisitor visitor, Boolean updateColumns)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.VisitChildren(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.RelationalInferredTypeMappingApplier.VisitExtension(Expression expression)
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQueryableMethodTranslatingExpressionVisitor.SqlServerInferredTypeMappingApplier.VisitExtension(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.RelationalInferredTypeMappingApplier.VisitExtension(Expression expression)
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQueryableMethodTranslatingExpressionVisitor.SqlServerInferredTypeMappingApplier.VisitExtension(Expression expression)
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQueryableMethodTranslatingExpressionVisitor.ApplyInferredTypeMappings(Expression expression, IReadOnlyDictionary`2 inferredTypeMappings)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)
   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.<ExecuteAsync>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.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToArrayAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)

The same happens for other NodaTime types, e.g. LocalTime.

Since the method throwing the exception is called ApplyTypeMappingsOnOpenJsonExpression, my guess is that's related to how EF Core 8 has changed generating SQL for Contains with parameter collections (it's now using OPENJSON instead of IN). More information can be found here.

This error doesn't occur when instead of using this library a custom converter for LocalDate is used:

class LocalDateCustomConverter : ValueConverter<LocalDate, DateTime>
{
    public LocalDateCustomConverter() : base(
        localDate => localDate.ToDateTimeUnspecified(),
        dateTime => LocalDate.FromDateTime(dateTime))
    {
    }
}

I've prepared a POC showing both cases:
https://github.com/rt-tidaro/EfCoreNodaTimeContainsBugPoc

Thanks for help!

@mcalypso
Copy link

mcalypso commented May 3, 2024

I have also run into this same problem.

@StevenRasmussen
Copy link
Owner

@ajcvickers - I know your time is limited and I'm hoping you might be able to help point me in the right direction on how to resolve this error. I've spent some time trying to research this issue and can deduce that I need to add some handling now for the Contains method, but it's unclear what else needs to be done so that the exception above is not thrown. I've created a working branch for this called contains-bug. You can reproduce the issue by running the test here. Thanks in advance!

@mcalypso
Copy link

I was able to get around this issue by adding the following to the ConfigureConventions of my DBContext:

configurationBuilder.Properties<LocalDate>().HaveConversion<LocalDateValueConverter>();

This uses the built-in LocalDateValueConverter that is defined in this repo.

@ajcvickers
Copy link
Contributor

@StevenRasmussen I've put it on my personal backlog and hopefully I'll get some time to look soon.

@StevenRasmussen
Copy link
Owner

@ajcvickers - With v9 being released might you have any time to take a look into this issue? Thanks!

@ajcvickers
Copy link
Contributor

@StevenRasmussen It's still on my list but I have been out sick for several months and have just got back. The holiday period is coming up, so that should give me some time to catch up.

@StevenRasmussen
Copy link
Owner

@ajcvickers - Sorry to hear about your health... never fun. I'm glad that you're doing better. Thanks so much for your assistance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants