Как удалить подчеркивание полей внешнего ключа в коде сначала по соглашению

code-first entity-framework entity-framework-6 naming-conventions

Вопрос

У меня есть несколько классов (включая TPT) в моем проекте. Каждый POCO имеет BaseClass , который имеет GUID (называемый GlobalKey ) в качестве первичного ключа.

Сначала я использовал DataAnnotations для создания правильных внешних ключей. Но тогда у меня проблемы с синхронизацией соответствующего GUID с самим объектом.

Теперь я хочу иметь только одно виртуальное свойство навигации, так что поле GUID в базе данных создается NamingConvention . Но имя поля всегда добавляет символ подчеркивания, за которым следует слово GlobalKey (это правильно). Когда я хочу удалить подчеркивание, я не хочу проходить через все мои POCO в свободном API для этого:

// Remove underscore from Navigation-Field     
modelBuilder.Entity<Person>()
            .HasOptional(x => x.Address)
            .WithMany()
            .Map(a => a.MapKey("AddressGlobalKey"));

Любые идеи сделать это для всех POCOS, перезаписав соглашение?

Заранее спасибо.

Andreas

Принятый ответ

Я, наконец, нашел для этого ответ, написав специальную конвенцию. Это соглашение работает в EF 6.0 RC1 (код с прошлой недели), поэтому я думаю, что он, скорее всего, продолжит работу после выпуска EF 6.0.

При таком подходе стандартные соглашения EF идентифицируют независимые ассоциации (IA), а затем создают EdmProperty для поля внешнего ключа. Затем это соглашение приходит и переименовывает поля внешнего ключа.

/// <summary>
/// Provides a convention for fixing the independent association (IA) foreign key column names.
/// </summary>
public class ForeignKeyNamingConvention : IStoreModelConvention<AssociationType>
{

    public void Apply(AssociationType association, DbModel model)
    {
        // Identify a ForeignKey properties (including IAs)
        if (association.IsForeignKey)
        {
            // rename FK columns
            var constraint = association.Constraint;
            if (DoPropertiesHaveDefaultNames(constraint.FromProperties, constraint.ToRole.Name, constraint.ToProperties))
            {
                NormalizeForeignKeyProperties(constraint.FromProperties);
            }
            if (DoPropertiesHaveDefaultNames(constraint.ToProperties, constraint.FromRole.Name, constraint.FromProperties))
            {
                NormalizeForeignKeyProperties(constraint.ToProperties);
            }
        }
    }

    private bool DoPropertiesHaveDefaultNames(ReadOnlyMetadataCollection<EdmProperty> properties, string roleName, ReadOnlyMetadataCollection<EdmProperty> otherEndProperties)
    {
        if (properties.Count != otherEndProperties.Count)
        {
            return false;
        }

        for (int i = 0; i < properties.Count; ++i)
        {
            if (!properties[i].Name.EndsWith("_" + otherEndProperties[i].Name))
            {
                return false;
            }
        }
        return true;
    }

    private void NormalizeForeignKeyProperties(ReadOnlyMetadataCollection<EdmProperty> properties)
    {
        for (int i = 0; i < properties.Count; ++i)
        {
            string defaultPropertyName = properties[i].Name;
            int ichUnderscore = defaultPropertyName.IndexOf('_');
            if (ichUnderscore <= 0)
            {
                continue;
            }
            string navigationPropertyName = defaultPropertyName.Substring(0, ichUnderscore);
            string targetKey = defaultPropertyName.Substring(ichUnderscore + 1);

            string newPropertyName;
            if (targetKey.StartsWith(navigationPropertyName))
            {
                newPropertyName = targetKey;
            }
            else
            {
                newPropertyName = navigationPropertyName + targetKey;
            }
            properties[i].Name = newPropertyName;
        }
    }

}

Обратите внимание, что Конвенция добавляется в ваш DbContext в вашем переопределении DbContext.OnModelCreating , используя:

modelBuilder.Conventions.Add(new ForeignKeyNamingConvention());

Популярные ответы

Я знаю, что это немного устарело, но вот пример того, как я указываю столбцы сопоставления через мою текущую конфигурацию (OnModelCreating):

modelBuilder.Entity<Application>()
            .HasOptional(c => c.Account)
                .WithMany()
                .Map(c => c.MapKey("AccountId"));

Надеюсь это поможет,



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему