AutoMapper / AutoMapper.Extensions.OData

Creates LINQ expressions from ODataQueryOptions and executes the query.
MIT License
140 stars 38 forks source link

Filter on unsigned type for trivially-mapped relation yields InvalidOperationException #204

Closed bhood-zorus closed 6 months ago

bhood-zorus commented 6 months ago

Source/destination types

// Source: EF entity
public class TestEntity
{
    public int Id { get; set; }
    public ulong UserId { get; set; }
}

// Destination: API model
public class TestModel
{
    public int? Id { get; set; }
    public ulong? UserId { get; set; }
}

Mapping configuration

public class TestModelProfile : Profile
{
    public TestModelProfile()
    {
        CreateMap<TestEntity, TestModel>();
    }
}

Version: 4.0.1

.NET 6 AutoMapper.AspNetCore.OData.EFCore 4.0.1 AutoMapper 12.0.1 AutoMapper.Collection 9.0.0 AutoMapper.Extensions.ExpressionMapping 6.0.4 AutoMapper.Extensions.DependencyInjection 12.0.1

Expected behavior

Results are returned normally

Actual behavior

System.InvalidOperationException: For members of literal types, use IMappingExpression.ForMember() to make the parent property types an exact match. Parent Source Type: System.Nullable`1[System.UInt64], Parent Destination Type: System.UInt64, Full Member Name "Value".

Steps to reproduce

Sample project: https://github.com/bhood-zorus/AutoMapperBugDemo Send a GET request to https://localhost:port/api/test?$filter=UserId eq 1

When the UserId property of TestEntity and TestModel is of type int and int? (respectively), the API request succeeds. When it's of an unsigned type (uint, ulong, etc.) the application throws the exception above.

The sample project uses an in-memory database for the sake of providing a simple repro. This behavior is currently being seen with a real-world MySQL database using the Pomelo EF provider. The only way I've been able to reproduce this problem has been to use the GetQueryAsync extension method, so I assume this is the appropriate repository to report it in.

BlaiseD commented 6 months ago

That exception is thrown here.. Best to reproduce it in that repository. Consider making the member types match using ForMember.

bhood-zorus commented 6 months ago

@BlaiseD Why does it work for int/int? but not uint/uint?? Perhaps I'm misunderstanding something, but your comment hasn't answered anything for me.

bhood-zorus commented 6 months ago

@BlaiseD I (hopefully) understand now that you were advising me to make the issue in that GitHub repository. I will do that.