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

Nullable ForeignKey in combination with orderBy and expand causes "Nullable object must have a value." exception with EF Core #1395

Open
MartinTopfstedtSinc opened this issue Jan 20, 2025 · 2 comments
Assignees
Labels
bug Something isn't working followup

Comments

@MartinTopfstedtSinc
Copy link

Assemblies affected
Microsoft.AspNetCore.OData: 9.1.3

Describe the bug
If there are 2 entities, where EntityA has a nullable foreign key to EntityB and EntityB has a nonnullable property, e.x an order number with type int, If there is a request which gets all EntityA objects with an orderBy of "EntityB/Order" and an expand for "EntityB" then the "Nullable object must have a value." exception gets thrown by ef core.

Reproduce steps
The following data is needed for reproduction. One EntityB object and 2 EntityA objects, one has the foreign key to EntityB set and the other has null instead.

{
    "EntityA": [
        {
            "Id": 1
           "EntityBId": 1
        },
        {
            "Id": 2
           "EntityBId": null
        },
    ],
    "EntityB": [
        {
            "Id": 1
            "Order": 1
            "DisplayName": "Test"
        }
    ]
}

Data Model

public class EntityA
{
    public int Id { get; set; }
    public int? EntityBId { get; set; } # nullable foreign key
    public EntityB EntityB { get; set; }
}

public class EntityB
{
    public int Id { get; set; }
    public int Order { get; set; }
    public string DisplayName { get; set; }
}

EDM (CSDL) Model

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
	<edmx:DataServices>
		<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="EfCoreNullableForeignKey">
			<EntityType Name="EntityA">
				<Key>
					<PropertyRef Name="Id"/>
				</Key>
				<Property Name="Id" Type="Edm.Int32" Nullable="false"/>
				<Property Name="DisplayName" Type="Edm.String"/>
				<Property Name="EntityBId" Type="Edm.Int32"/>
				<NavigationProperty Name="EntityB" Type="EfCoreNullableForeignKey.EntityB">
					<ReferentialConstraint Property="EntityBId" ReferencedProperty="Id"/>
				</NavigationProperty>
			</EntityType>
			<EntityType Name="EntityB">
				<Key>
					<PropertyRef Name="Id"/>
				</Key>
				<Property Name="Id" Type="Edm.Int32" Nullable="false"/>
				<Property Name="DisplayName" Type="Edm.String"/>
				<Property Name="Order" Type="Edm.Int32" Nullable="false"/>
			</EntityType>
		</Schema>
		<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Default">
			<EntityContainer Name="Container">
				<EntitySet Name="EntityA" EntityType="EfCoreNullableForeignKey.EntityA">
					<NavigationPropertyBinding Path="EntityB" Target="EntityB"/>
				</EntitySet>
				<EntitySet Name="EntityB" EntityType="EfCoreNullableForeignKey.EntityB"/>
			</EntityContainer>
		</Schema>
	</edmx:DataServices>
</edmx:Edmx>

Request/Response
Request: /odata/EntityA?$orderBy=EntityB/Order&$expand=EntityB($select=Id)
Response: None Exception is thrown and Stream gets cut off.

Expected behavior
The collection of EntityA should be returned as requested. It should order the collection and expand the EntityA navigation properties if they are not null.

Screenshots
None

Additional context
The request works correct if there is only the orderBy or the expand, but both in combination will throw an exception.

The request will work correctly as well when an nullable property is used in the orderBy clause.

This is a minimal viable reproduction project. You can trigger the requests from the "EfCoreNullableForeignKey.http" file.
EfCoreNullableForeignKey.zip

@MartinTopfstedtSinc MartinTopfstedtSinc added the bug Something isn't working label Jan 20, 2025
@xuzhg
Copy link
Member

xuzhg commented Jan 21, 2025

If you change the configuration on the controller/action as belows:
[EnableQuery(HandleNullPropagation = HandleNullPropagationOption.True)]

Then you can send request as:

https://localhost:7229/odata/EntityA?$orderBy=EntityB/DisplayName&$expand=EntityB($select=Id)

You can get as below:

Image

If you send request as:

https://localhost:7229/odata/EntityA?$orderBy=EntityB/Order&$expand=EntityB($select=Id, DisplayName)

You can get:

Image

@MartinTopfstedtSinc
Copy link
Author

Hi,

thanks, this works like a charm. Can i set this globally or does this only work with the EnableQueryAttribute?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working followup
Projects
None yet
Development

No branches or pull requests

3 participants