AspNetCoreOData icon indicating copy to clipboard operation
AspNetCoreOData copied to clipboard

IN Operator filter function stopped working after upgrading project to .net 8

Open emjotnau opened this issue 1 year ago • 7 comments

Assemblies affected 8.2.3

Describe the bug "in" operator used in request filter on .net 8 application throws an exception.:

The LINQ expression '__TypedProperty_0
    .Contains(MaterializeCollectionNavigation(
        Navigation: Country.Translations,
        subquery: DbSet<CountryTranslation>()
            .Where(i => EF.Property<Guid?>(StructuralTypeShaperExpression: 
                Ewl.Platform.Geo.Storage.Entities.Country
                ValueBufferExpression: 
                    ProjectionBindingExpression: EmptyProjectionMember
                IsNullable: False
            , "Id") != null && object.Equals(
                objA: (object)EF.Property<Guid?>(StructuralTypeShaperExpression: 
                    Ewl.Platform.Geo.Storage.Entities.Country
                    ValueBufferExpression: 
                        ProjectionBindingExpression: EmptyProjectionMember
                    IsNullable: False
                , "Id"), 
                objB: (object)EF.Property<Guid?>(i, "CountryId"))))
        .AsQueryable()
        .Select(s => s.Name)
        .ElementAt(0))' 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.

It occurs when in operator is used to query collection of children. Name property comes from Translation entity and is retrieved this way:

 return (e) => new CountryListDto
 {
     Id = e.Id,
     Name = e.Translations.First().Name,
 }

Reproduce steps Request: https://.../countries?$filter=name in ('Angola')

Data Model

public class Country
{
  public Guid Id { get; set; }
  public ICollection<CountryTranslation> Translations { get; set; } = null!;
}
 public class CountryTranslation 
 {
     public Guid CountryId { get; set; }
     public Country Country { get; set; } = null!;
     public string Name { get; set; } = null!;
}

EDM (CSDL) Model

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
    <edmx:DataServices>
        <Schema Namespace="Dtos" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityType Name="CountryListDto">
                <Key>
                    <PropertyRef Name="id" />
                </Key>
                <Property Name="id" Type="Edm.Guid" Nullable="false" />
                <Property Name="name" Type="Edm.String" Nullable="false" MaxLength="64" />               
            </EntityType>            
        </Schema>       
        <Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityContainer Name="Container">
                <EntitySet Name="countries" EntityType="Dtos.CountryListDto" />               
            </EntityContainer>
        </Schema>
    </edmx:DataServices>
</edmx:Edmx>

Request/Response https://.../countries?$filter=name in ('Angola')

Expected behavior List of countries is returned in response

emjotnau avatar Nov 23 '23 09:11 emjotnau

Thank you @emjotnau for reporting the issue. Could you please confirm if it works in .NET7 and .NET6?

gathogojr avatar Nov 28 '23 17:11 gathogojr

@emjotnau Please also confirm if you were using EF Core or EF6 before it stopped working. It'd help if you can share a repro for us to look at.

gathogojr avatar Nov 28 '23 17:11 gathogojr

@gathogojr, Thanks for showing interest, I do confirm, it works on .net6 and .net7

emjotnau avatar Nov 30 '23 07:11 emjotnau

@gathogojr Please take a look at simple project of API which the issue can be reproduced on: https://github.com/emjotnau/InOperatorTest

Request: https://localhost:7048/cr/countries?$filter=name in ('name2'),

Thank You

emjotnau avatar Dec 11 '23 12:12 emjotnau

Could it be related to the breaking change of EF 8? "Contains in LINQ queries may stop working on older SQL Server versions" https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/breaking-changes#contains-in-linq-queries-may-stop-working-on-older-sql-server-versions

skarpovru avatar Dec 28 '23 16:12 skarpovru

Could it be related to the breaking change of EF 8? "Contains in LINQ queries may stop working on older SQL Server versions" https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/breaking-changes#contains-in-linq-queries-may-stop-working-on-older-sql-server-versions

I have already checked it and in my reckoning that is not the case.

emjotnau avatar Dec 29 '23 07:12 emjotnau

any news?

emjotnau avatar Feb 16 '24 07:02 emjotnau