AutoMapper / AutoMapper.Extensions.OData

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

TimeOnly values not automatically selected in query #138

Closed leoerlandsson closed 2 years ago

leoerlandsson commented 2 years ago

When projecting a query for an entity containing properties of the type TimeOnly (new in .NET6), the values are not automatically selected. Instead, they are ignored and therefore are returned as null in the OData response.

I guess TimeOnly is currently not supported. Support was added in OData 8.0.7: https://github.com/OData/AspNetCoreOData/releases/tag/8.0.7

Could this be related to TimeOfDay being mapped to TimeOfDay in Constants.cs ? https://github.com/AutoMapper/AutoMapper.Extensions.OData/blob/master/AutoMapper.AspNetCore.OData.EFCore/Constants.cs

[new EdmTypeStructure("Edm.TimeOfDay", false)] = typeof(TimeOfDay), [new EdmTypeStructure("Edm.TimeOfDay", true)] = typeof(TimeOfDay?),

A workaround is to include the TimeOnly properties in the $select, but that involves adding all properties that you want returned in the OData response.

Would it be possible to support TimeOnly?

Thanks.

Examples: Before mapping the query:

DbSet<OpeningHours>()
    .Where(e => EF.Property<object>(e, <>c__DisplayClass9_0.keyProperty.Name) == <>c__DisplayClass9_0.key)
    .AsNoTracking()
(SQL: SELECT [o].[Id], [o].[Created], [o].[CreatedBy], [o].[EndTime], [o].[Modified], [o].[ModifiedBy], [o].[StartTime], [o].[SubAreaId], [o].[Type], [o].[ValidFrom], [o].[ValidTo]
FROM [OpeningHours] AS [o]
WHERE [o].[Id] = @__key_0)

After mapping (note that the properties StartTime and EndTime are not automatically selected, as they are of the TimeOnly type): DbSet<OpeningHours>() .Where(e => EF.Property<object>(e, <>c__DisplayClass9_0.keyProperty.Name) == <>c__DisplayClass9_0.key) .AsNoTracking() .Select(dtoOpeningHours => new OpeningHoursDTO{ Type = dtoOpeningHours.Type, ValidFrom = dtoOpeningHours.ValidFrom, ValidTo = dtoOpeningHours.ValidTo, SubAreaId = dtoOpeningHours.SubAreaId, Id = dtoOpeningHours.Id, Created = dtoOpeningHours.Created, Modified = dtoOpeningHours.Modified, CreatedBy = dtoOpeningHours.CreatedBy, ModifiedBy = dtoOpeningHours.ModifiedBy } )

BlaiseD commented 2 years ago

Yep - that's not supported yet. Building selectors for literal expressions depends on a list in a referenced library here.

PRs are welcome. We'll probably want to support DateOnly at the same time.

EdmToClrTypeMappings in constants probably needs fixing too - may want to consider how the latest AspNetCoreOData converts Edm.TimeOfDay and Edm.Date. i.e. TimeOnly/ DateOnly vs Microsoft.OData.Edm.Date/Microsoft.OData.Edm.TimeOfDay. Could be new corresponding EDM types were added for DateOnly/TimeOnly.

BlaiseD commented 2 years ago

This should work now in the myget build.

leoerlandsson commented 2 years ago

Nice work, thank you @BlaiseD!

We'll test it right away.

leoerlandsson commented 2 years ago

Verified, and it works. TimeOnly and DateOnly are returned. Thank you!

BlaiseD commented 2 years ago

v3.0.5. Thanks for verifying.