I have an entity DataSuggestion
which owns Data
. Data
itself owns Material
& Coordinates
.
public class DataSuggestion : Entity<Guid>
{
public Guid DataId { get; init; }
public Email Email { get; init; }
public Comment Comment { get; init; }
public Data Data { get; init; }
public DataSuggestion(Email email,
Comment comment,
IEnumerable<Coordinate> coordinates,
Material material) : this()
{
Email = email;
Comment = comment;
Data = new Data(coordinates, material);
}
private DataSuggestion()
{ }
}
public class Data : ValueObject<Data>
{
private readonly List<Coordinate> _coordinates;
public IEnumerable<Coordinate> Coordinates => _coordinates.AsReadOnly();
public Material Material { get; init; }
public Data(IEnumerable<Coordinate> coordinates,
Material material) : this()
{
_coordinates = coordinates.ToList();
Material = material;
}
/// <summary>
/// EF Core constructor
/// </summary>
private Data()
{ }
protected override IEnumerable<object> GetAttributesToIncludeInEqualityCheck()
{
return [_coordinates, Material];
}
}
The configuration is as follows
builder.OwnsOne(ds => ds.Comment);
builder.OwnsOne(ds => ds.Email);
builder.OwnsOne(ds => ds.Data, ownedNavigationBuilder =>
{
ownedNavigationBuilder.OwnsOne(d => d.Material);
ownedNavigationBuilder.OwnsMany(d => d.Coordinates);
ownedNavigationBuilder.Navigation(d => d.Material).IsRequired();
});
I get an exception:
Entity type 'Data' is an optional dependent using table sharing and containing other dependents without any required non shared property to identify whether the entity exists. If all nullable properties contain a null value in database then an object instance won't be created in the query causing nested dependent's values to be lost. Add a required property to create instances with null values for other properties or mark the incoming navigation as required to always create an instance.
As far as I understand the exception states that if none of Data
's properties must not be null. However, I've already marked Material as required (EDIT: by this I mean ownedNavigationBuilder.Navigation(d => d.Material).IsRequired();
), and it's not possible to do the same for collections.
Also I'm a bit confused: DataSuggestion
owns Comment
which contains only string property, but such an exception is not thrown.
I've tried to mark whole Data
as required but to no avail.
The questions are:
Coordinates
as required?Thank you!
EDIT: I've found out that the order of instructions matter and if I put
uilder.Navigation(ds => ds.Data).IsRequired();
After
builder.OwnsOne(ds => ds.Data, ownedNavigationBuilder =>
{
ownedNavigationBuilder.OwnsOne(d => d.Material);
ownedNavigationBuilder.Navigation(d => d.Material).IsRequired();
ownedNavigationBuilder.OwnsMany(d => d.Coordinates);
});
Then it works, but still why isn't this enough?
ownedNavigationBuilder.Navigation(d => d.Material).IsRequired();
Material
and Coordinates
aren't properties but Owned Types/Collections, and if Data
itself does not contain any non-null properties, then no instance of Data
will be created, regardless of Material
values.
I've annotated the exception message to help explain it.
Entity type 'Data' is an optional dependent (you didn't use .IsRequired() on
Data
itself) using table sharing and containing other dependents (Material
andCoordinates
) without any required non shared property (Data
does not contain a property, owned types/collections don't count) to identify whether the entity exists. If all nullable properties (This is the case if you don't have any properties) contain a null value in database then an object instance (ofData
) won't be created in the query causing nested dependent's (Material
) values to be lost. Add a required property to create instances with null values for other properties or mark the incoming navigation as required to always create an instance.