Каковы изменения EF Core 2.1 в собственных типах?


Docs последний раз менялся 26.02.2018, но есть некоторые критические изменения, которые мне нужно исправить.

У меня есть Тип MyProcessContext, используемый как принадлежащий для многих сущностей:

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();
    }
}

Он работает, как и ожидалось, с EF Core 2.0. В представлении отладки у меня есть разные типы сущностей для каждого использования собственного типа (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]    

После обновления отладочное представление содержит

  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]

Модель, построенная как MyProcessContext, является обычной сущностью. В коде типа

foreach (var entity in modelBuilder.Model.GetEntityTypes())
            {
                var entityIsOwned = entity.IsOwned();

entityIsOwned верно, но entity.DefiningNavigationName Теперь равно нулю.

Мне нужно это имя дляпользовательского соглашения имен .

1 2

1 ответ:

Единственным официальным изменением на данный момент (ядро EF 2.1) является добавление атрибута [Owned] .

Однако, по-видимому, есть прорывные изменения в реализации, поэтому свойства DefiningEntityType и DefiningNavigationName не являются более надежными (они все равно не документируются - просто "стандартный" сгенерированный бесполезный "получает определяющий тип сущности." и "получает имя определяющей навигации.").

Экспериментально я обнаружил, что они заселяются только в том случае, если владелец тип используется в нескольких сущностях. Не знаю, почему они это делают, но главное, что мы не должны их использовать, более того, сам код ядра EF, похоже, больше не использует их.

Из того, что я видел, IsOwned, DefiningEntityType а члены DefiningNavigationName определяются внешним ключом, имеющим свойство IsOwnership, равное true.

Другими словами:

var ownershipFk = entityType.GetForeignKeys().FirstOrDefault(fk => fk.IsOwnership);
var isOwned = ownershipFk != null;
var definingEntityType = ownershipFk?.PrincipalEntityType;
var definingNavigationName = ownershipFk?.PrincipalToDependent.Name;