Как использовать пользовательское соглашение об именах с принадлежащими типами?

public class ProcessInitialization
{
    public Guid CorrelationId { get; set; }
    public MyProcessContext ProcessContext { get; set; }
}

public class MyProcessContext
{
    public int? ProcessId { get; set; }
}

Без использования моего соглашения я получил

SELECT `process`.`CorrelationId`
FROM `ProcessInitialization` AS `process`
WHERE `process`.`ProcessContext_ProcessId` = 8

Мое соглашение делает snake_case из PascalCase:

public static void SetSimpleUnderscoreTableNameConvention(this ModelBuilder modelBuilder,
    bool preserveAcronyms,
    IDictionary<string, string> propertyMap = null,
    IDictionary<string, string> entityMap = null
    )
{
    var propMap = propertyMap ?? new Dictionary<string, string>();
    var entMap = entityMap ?? new Dictionary<string, string>();

    foreach (var entity in modelBuilder.Model.GetEntityTypes())
    {
        foreach (var prop in entity.GetProperties())
        {
            if (propMap.ContainsKey(prop.Name))
            {
                prop.Relational().ColumnName = propMap[prop.Name];
            }
            else
            {
                var underscoredProp = AddUndercoresToSentence(prop.Name, preserveAcronyms);
                prop.Relational().ColumnName = underscoredProp.ToLowerInvariant();
            }
        }

        var entName = entity.DisplayName();

        if (entMap.ContainsKey(entName))
        {
            entity.Relational().TableName = entMap[entName];
        }
        else
        {
            var underscored = AddUndercoresToSentence(entity.DisplayName(), preserveAcronyms);
            entity.Relational().TableName = underscored.ToLowerInvariant();
        }
    }
}

С ним запрос становится недействительным:

SELECT `process`.`correlation_id`
FROM `process`
LEFT JOIN `process_initialization._process_context#_my_process_context` AS `process.ProcessContext` ON `process`.`correlation_id` = `process.ProcessContext`.`process_initialization_correlation_id`
WHERE `process.ProcessContext`.`process_id` = 8

Похоже, мне не нужно применять преобразование к некоторым из entity:

var underscored = AddUndercoresToSentence(entity.DisplayName(), preserveAcronyms);
if (underscored.Contains("#")) // any other way to understand it is special?
    continue;
entity.Relational().TableName = underscored.ToLowerInvariant();

После этого я получил:

Ключи {'ProcessInitializationCorrelationId'} в 'ProcessInitialization.ProcessContext#MyProcessContext' и {'CorrelationId'} в 'ProcessInitialization' сопоставляются с 'process_initialization.PK_process_initialization', но с разными столбцами ({'process_initialization_correlation_id'} и {'correlation_id'} ).


person smg    schedule 08.12.2017    source источник


Ответы (1)


Принадлежащие типы требуют специальной обработки.

Во-первых, вы узнаете их, используя метод IEntityType.IsOwned().

Затем, когда тип сущности является владельцем, вы должны пропустить сопоставление имени таблицы (поскольку они совместно используют ту же таблицу, что и сущность корневого владельца). Также собственные типы имеют теневые свойства PK, которые следует пропустить, а для других свойств вы должны построить имя столбца из пути от корневого владельца до принадлежащего типа. Информация о владельце доступна через DefiningEntityType и DefiningNavigationName свойства IEntityType.

Применение всего этого к вашему коду:

foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
    foreach (var prop in entity.GetProperties())
    {
        if (entity.IsOwned() && prop.IsPrimaryKey()) continue;
        IEntityType propOwner = entity;
        string propName = prop.Name, columnName = null;
        do
        {
            if (!propMap.TryGetValue(propName, out var name))
                name = AddUndercoresToSentence(propName, preserveAcronyms).ToLowerInvariant();
            columnName = columnName == null ? name : name + "_" + columnName;
            propName = propOwner.DefiningNavigationName;
            propOwner = propOwner.DefiningEntityType;
        }
        while (propName != null);
        prop.Relational().ColumnName = columnName;
    }

    if (entity.IsOwned()) continue;
    var entName = entity.DisplayName();
    if (!entMap.TryGetValue(entName, out var tableName))
        tableName = AddUndercoresToSentence(entName, preserveAcronyms).ToLowerInvariant();
    entity.Relational().TableName = tableName;
}
person Ivan Stoev    schedule 08.12.2017