OData / OData/AspNetCoreOData

Issue with expand+select on nullable property of a DTO

Open
#302 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

followup
Dominant language
C#
Stars
505
Forks
186
PR merge metrics
No merged PRs in 30d

Description

The GET of my OData controller return basically something like this:

var customers = (from customer in _companyDbContext.CustomerEntities
                 select new CustomerDto
                 {
                     Id = customer.Id,
                     Code = customer.Code,
                     Warehouse = customer.Warehouse == null ? null : new WarehouseDto
                     {
                         Id = customer.Warehouse.Id,
                         Code = customer.Warehouse.Code
                     }
                 });

It does not return EF Core entities directly. We create a CustomerDto, containing a WarehouseDto which can be null.

When i do $expand=warehouse($select=id) i get the following error:

Rewriting child expression from type 'System.Int32' to type 'System.Nullable`1[System.Int32]' is not allowed, because it would change the meaning of the operation. If this is intentional, override 'VisitUnary' and change it to allow this rewrite.

I can avoid the issue by changing the type of WarehouseDto.Id from int to int?. So, i will go with this workaround for now.

For info, i don't get the issue when i don't have to check for null.

var customers = (from customer in _companyDbContext.CustomerEntities
                 select new CustomerDto
                 {
                     Id = customer.Id,
                     Code = customer.Code,
                     WarehouseDto = new Warehouse
                     {
                         Id = customer.Warehouse.Id,
                         Code = customer.Warehouse.Code
                     }
                 });

But when the column contains a null, it give me an "Nullable object must have a value" error.

I have another workaround without changing WarehouseDto.Id from int to int?.
I introduce an intermediary let variable.

var customers = (from customer in _companyDbContext.CustomerEntities
                 let warehouse = new WarehouseDto
                 {
                     Id = customer.Warehouse == null ? 0 : customer.Warehouse.Id,
                     Code = customer.Warehouse.Code
                 }
                 select new CustomerDto
                 {
                     Id = customer.Id,
                     Code = customer.Code,
                     Warehouse = warehouse.Id == 0 ? null : warehouse
                 });

I played with [EnableQuery(HandleNullPropagation = HandleNullPropagationOption.True)], True or False and i don't get much difference.

It works with $expand=warehouse($select=*)
I use AspNetCore.OData 8.0.1 and EFCore 5.0.7.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the DTO projection from the issue with AspNetCore.OData 8.0.1 and EFCore 5.0.7, using $expand=warehouse($select=id) and a nullable Warehouse. Compare the failing nullable-property rewrite with the working workarounds and HandleNullPropagation settings. Done means the projection supports the selected nullable navigation property without the rewrite or nullable-value exception while preserving null results.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.