I was really looking forward to the new Owned Entities feature until I found out that struct types are not supported.
Common examples of struct types:
```c#
struct Vector3 {
float X { get; set; }
float Y { get; set; }
float Z { get; set; }
}
struct TimeRange {
DateTime StartTime { get; set; }
DateTime EndTime { get; set; }
}
struct Date {
private readonly DateTime _dt;
public UtcDate(int year, int month, int day)
{
_dt = new DateTime(year, month, day, 0, 0, 0, DateTimeKind.Utc);
}
...
}
Similar Struct Types in third party libraries: [corefxlab](https://github.com/dotnet/corefxlab/blob/master/src/System.Time/System/Date.cs) [NodaTime](https://github.com/nodatime/nodatime/blob/master/src/NodaTime/LocalDate.cs)
I would like to use these struct types in my entities:
```c#
class Event {
string Name { get;set; }
TimeRange TimeRange { get; set; }
}
class BankHoliday {
string Name { get;set; }
Date Date { get; set; }
}
modelBuilder.Entity<Event>().OwnsOne(e => e.TimeRange);
modelBuilder.Entity<BankHoliday>().OwnsOne(e => e.Date);
so that the generated tables look like these:
Event [Name, TimeRange_StartTime, TimeRange_EndTime]
BankHoliday [Name, Date_dt]
Good point.
Value types (like an address type for instance) are most likely to be mapped as an Owned Entity. Value types are mostly represented by structs, so not having the possibility to map a struct as an 'owned entity' could indeed be a dealbreaker.
It seems like nullable owned entities are also not supported.
@sir-boformer - nullable owned entities are covered by #9005 If you map them to different table then they can work.
Why would you want to map an owned entity to a different table ? In most cases, I want them to be part of the owning table. Nullable owned entities are a valid use-case, especially if the database already exists ...
@fgheysels - That is valid use-case. At present, when they are mapped in same table, they uses same column for PK. In current implementation there is no way to figure out if the owned entity is null. So if you map it to separate table, you can find out owned entity is null when no matching row is found. It is not ideal and users would want to map it to same table hence #9005 is the tracking issue to implement support for it.
Notes from triage: we think the common cases for structs like these could be handled by being able to map a type to multiple columns. The main missing feature for this is type mapping from a single property to multiple columns.
@smitpatel - I think that , when using owned entities as a value type (which will be for me the most obvious usage of owned entities), you should not think in terms of primary keys. A value type is not an entity and has no identifier; it's identity is made up by its value.
@ajcvickers I'm a fond user of NHibernate, and there this is done using 'component-mapping'. Maybe helpfull to take a look at it ? http://nhibernate.info/doc/nhibernate-reference/components.html
Note: consider the case that the value object contains key properties--see #10682
This prevents me from reusing my models, as I'm using struct for related properties set heavily.
It works for classes but not for structs. If you try to use struct
with OwnsOne
you get error: error CS0452: The type 'Vector' must be a reference type in order to use it as parameter 'TRelatedEntity' in the generic type or method 'EntityTypeBuilder<Player>.OwnsOne<TRelatedEntity>(Expression<Func<Player, TRelatedEntity>>)
It says clearly that Vector
must be a reference type (class
) but struct
is a value type.
See also https://github.com/aspnet/EntityFrameworkCore/issues/13947#issuecomment-457353765
Most helpful comment
Notes from triage: we think the common cases for structs like these could be handled by being able to map a type to multiple columns. The main missing feature for this is type mapping from a single property to multiple columns.