Docs last changed at 02/26/2018, but there is some breaking changes that I need to fix.
I have MyProcessContext
type, used as owned for many entities:
public class RequestData
{
public Guid CorrelationId { get; set; }
public DateTime Updated { get; set; }
public MyProcessContext ProcessContext { get; set; }
}
public class MyProcessContext
{
public int ClientId { get; set; }
}
public class EntityConfiguration : IEntityTypeConfiguration<RequestData>
{
public void Configure(EntityTypeBuilder<RequestData> builder)
{
// all mapped by convention
builder.OwnsOne(x => x.ProcessContext);
builder.Property(x => x.Updated).IsRowVersion();
builder.HasKey(x => x.CorrelationId);
builder.Property(x => x.CorrelationId).ValueGeneratedNever();
}
}
It works as expected with EF Core 2.0. In debug view I have different entity type for each usage of owned type (RequestData.ProcessContext#MyProcessContext
):
EntityType: RequestData
Properties:
CorrelationId (Guid) Required PK AfterSave:Throw 0 0 0 -1 -1
Annotations:
Relational:ColumnName: correlation_id
Updated (DateTime) Required Concurrency BeforeSave:Ignore AfterSave:Ignore ValueGenerated.OnAddOrUpdate 11 11 -1 -1 0
Annotations:
Relational:ColumnName: updated
Navigations:
ProcessContext (<ProcessContext>k__BackingField, MyProcessContext) ToDependent RequestData.ProcessContext#MyProcessContext 0 -1 1 -1 -1
Keys:
CorrelationId PK
Annotations:
Relational:TableName: process_request
RelationshipDiscoveryConvention:NavigationCandidates: System.Collections.Immutable.ImmutableSortedDictionary`2[System.Reflection.PropertyInfo,System.Type]
EntityType: RequestData.ProcessContext#MyProcessContext
Properties:
RequestDataCorrelationId (no field, Nullable<Guid>) Shadow Required PK FK AfterSave:Throw 0 0 0 0 -1
ClientId (int) Required 1 1 -1 -1 -1
Keys:
RequestDataCorrelationId PK
Foreign keys:
RequestData.ProcessContext#MyProcessContext {'RequestDataCorrelationId'} -> RequestData {'CorrelationId'} Unique ToDependent: ProcessContext
Annotations:
Relational:TableName: process_request
RelationshipDiscoveryConvention:NavigationCandidates: System.Collections.Immutable.ImmutableSortedDictionary`2[System.Reflection.PropertyInfo,System.Type]
After upgrade debug view contains
EntityType: RequestData
...
ProcessContext (<ProcessContext>k__BackingField, MyProcessContext) ToDependent MyProcessContext 0 -1 1 -1 -1
...
EntityType: MyProcessContext
Properties:
RequestDataCorrelationId (no field, Guid) Shadow Required PK FK AfterSave:Throw 0 0 0 0 -1
ClientId (int) Required 1 1 -1 -1 -1
Keys:
RequestDataCorrelationId PK
Foreign keys:
MyProcessContext {'RequestDataCorrelationId'} -> RequestData {'CorrelationId'} Unique Ownership ToDependent: ProcessContext
Annotations:
Relational:TableName: process_request
RelationshipDiscoveryConvention:NavigationCandidates: System.Collections.Immutable.ImmutableSortedDictionary`2[System.Reflection.PropertyInfo,System.Type]
Model built like MyProcessContext
is usual entity. In code like
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
var entityIsOwned = entity.IsOwned();
entityIsOwned
is true, but entity.DefiningNavigationName
is null now.
I need that name for custom name convention.
The only official change so far (EF Core 2.1) is the addition of the [Owned] Attribute.
However apparently there are breaking changes in the implementation, so DefiningEntityType
and DefiningNavigationName
properties are no more reliable (they are not documented anyway - just the "standard" generated useless "Gets the defining entity type." and "Gets the name of the defining navigation.").
By experiment I've found that they are populated only if the owned type is used in more than one entity. Not sure why they do that, but the main point is that we should not use them, moreover the EF Core code itself also seems to not use them anymore.
From what I saw, IsOwned
, DefiningEntityType
and DefiningNavigationName
terms are determined by the foreign key having IsOwnership
property equal to true
.
In other words:
var ownershipFk = entityType.GetForeignKeys().FirstOrDefault(fk => fk.IsOwnership);
var isOwned = ownershipFk != null;
var definingEntityType = ownershipFk?.PrincipalEntityType;
var definingNavigationName = ownershipFk?.PrincipalToDependent.Name;