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 owned entity with nested owned entity always NOT NULL #29457

Closed
MaximMikhisor opened this issue Oct 31, 2022 · 6 comments
Closed

Nullable owned entity with nested owned entity always NOT NULL #29457

MaximMikhisor opened this issue Oct 31, 2022 · 6 comments

Comments

@MaximMikhisor
Copy link

Model example

Note: <Nullable>enable</Nullable> is enabled for project.

    public class RootEntity
    {
        public Int32 Id { get; set; }

        public NestedOwnedEntity? NestedOwned { get; set; }

        public SimpleOwnedEntity? SimpleOwned { get; set; }
    }

    [Owned]
    public class NestedOwnedEntity
    {
        public SomeOwnedEntity? SomeOwned { get; set; }        
    }

    [Owned]
    public class SimpleOwnedEntity
    {
        public String? AProperty { get; set; }
    }

    [Owned]
    public class SomeOwnedEntity
    {
        public String? BProperty { get; set; }
    }

Current behaviour

NestedOwnedEntity has nested SomeOwnedEntity in model example above.
RootEntity has nullable NestedOwned property.
This property is always NOT NULL.

RootEntity also has nullable SimpleOwned property.
SimpleOwnedEntity has not any nested owned properies.
SimpleOwned property is NULL inside RootEntity if it was not assigned before.

NestedOwned property and SimpleOwned property behave in different way in regard to nullability.

Expected behaviour

It is expected that NestedOwned property to be NULL if it was not assigned before.
At this moment it is always NOT NULL.

Code sample

https://github.com/LineSmarts/EfCoreNotNullNestedOwned

Provider and version information

EF Core version : 5.0.17
Database provider: Microsoft.EntityFrameworkCore.Sqlite
Target framework: .NET 3.1
Operating system: Windows 10

@ajcvickers
Copy link
Member

@MaximMikhisor This type of model is explicitly disallowed starting with EF Core 6.0. See https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/breaking-changes#nested-optionals

@MaximMikhisor
Copy link
Author

Dear @ajcvickers , thank you for you answer.

Using models with nested optional dependents sharing a table and with no required properties often resulted in silent data loss.

The rules for optional dependents (as opposed to required dependents) say that if all of the columns for ContactInfo are null, then no instance of ContactInfo will be created when querying for the owner Customer. However, this also means that no instance of Address will be created, even if the Address columns are non-null.

Personaly for me I do not see here any data loss.
If ContactInfo had NOT NULL Address at some point, and after that ContactInfo has NULL Address -- it means that someone intentionaly set it up to NULL, i.e. someone does not need Address data any more.
So it does not metter that Address columns are non-null (maybe only disk space wasting).

Please correct me if I understood wrong what does it mean data loss in this case.

Mitigations:
...
2. Make sure that the dependent contains at least one required property.

Does it mean if I made AProperty and BProperty required my model example above will work fine in EfCore 6.0?
I.e. NestedOwned and SimpleOwned properties in RootEntity will be NULL if they were not assigned before?

@ajcvickers
Copy link
Member

@MaximMikhisor For 1, the point is that the nested owned entity may have data, but if the owned entity that it is nested in does not, then the date in the nested entity is lost.

For 2, no, because NestedOwnedEntity does not contain any properties at all, other than the navigation to SomeOwnedEntity. This is a very unusual thing to do; NestedOwnedEntity is not mapped to any database columns, and so all information about it is erased when it is saved to the database.

@MaximMikhisor
Copy link
Author

For 1, the point is that the nested owned entity may have data, but if the owned entity that it is nested in does not, then the date in the nested entity is lost.

Thank you for your explanation.

In explanation from your link above:

"The rules for optional dependents (as opposed to required dependents) say that if all of the columns for ContactInfo are null, then no instance of ContactInfo will be created when querying for the owner Customer. However, this also means that no instance of Address will be created, even if the Address columns are non-null."

It is a bit missleading descritpion. It looks like we lost Address data. But as I understood later it means that we lost ContactInfo object. Because at some point it existed in Customer object (even if ContactInfo contained not data itself). But after saving and querying in new place Customer oject will have NULL as ContactInfo.

Better example I found here:
#24558 (comment)

PS:
Think it is not good solution instead of fixing rules for optional dependents, just disallow to use this type of model.
Though I guess that proper solution cost a lot of resources and you just chose simple solution.

@MaximMikhisor
Copy link
Author

MaximMikhisor commented Nov 3, 2022

NestedOwnedEntity does not contain any properties at all, other than the navigation to SomeOwnedEntity. This is a very unusual thing to do

In our real code we have these two owned entities:

[Owned]
public class Location
{
    public Double Longitude { get; set; }
    public Double Latitude { get; set; }
}

[Owned]
public class LocationLine
{
    public Location Start { get; set; }
    public Location End { get; set; }
}

public class SomeParentEntity
{
    public LocationLine? Direction { get; set; }
    
    // Other properties....
}

It is sad that EF Core does not support this type of model.

@roji
Copy link
Member

roji commented Nov 3, 2022

Duplicate of #24558

@roji roji marked this as a duplicate of #24558 Nov 3, 2022
@roji roji closed this as not planned Won't fix, can't repro, duplicate, stale Nov 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants