Измените имя столбца Identity для всех объектов

entity-framework entity-framework-6

Вопрос

Я занимаюсь созданием модели домена и хотел бы иметь класс «BaseEntity» с свойством «Id» (и некоторыми другими материалами отслеживания аудита). Свойство Id - это первичный ключ, и каждый объект Entity в моей модели домена наследует класс BaseEntity. Довольно простой материал .....

public class BaseEntity
{
    [Key]
    public int Id { get; set; }

    public DateTime LastUpdate { get; set; }
    public string LastUpdateBy { get; set; }
}
public class Location : BaseEntity
{
    [Required]
    public string Name { get; set; }

    public string Description { get; set; }
}

Используя приведенный выше пример, я хотел бы сопоставить поле «Id» с столбцом «LocationId». Я понимаю, что я могу использовать modelBuilder, чтобы сделать это для каждого объекта явно, делая что-то вроде этого:

public class BaseEntity
{
    [Key]
    public int Id { get; set; }

    public DateTime LastUpdate { get; set; }
    public string LastUpdateBy { get; set; }
}
public class Location : BaseEntity
{
    [Required]
    public string Name { get; set; }

    public string Description { get; set; }
}

Но я хотел бы сделать это для каждой Entity в моей модели домена, и это было бы уродливо.

Я пробовал следующий бит рефлексии, но мне не повезло. По какой-то причине компилятор «не может разрешить тип символа»:

public class BaseEntity
{
    [Key]
    public int Id { get; set; }

    public DateTime LastUpdate { get; set; }
    public string LastUpdateBy { get; set; }
}
public class Location : BaseEntity
{
    [Required]
    public string Name { get; set; }

    public string Description { get; set; }
}

Есть ли способ определить соглашение, чтобы переопределить соглашение по умолчанию PrimaryKey для сопоставления моего свойства «Id» с свойством «ClassNameId» в базе данных? Я использую Entity Framework 6.

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

Вы должны взглянуть на пользовательские коды первых конвенций . Для этого вам нужен EF6, но похоже, что вы уже используете его.
Чтобы дать вам обзор, взгляните на следующее соглашение, которое я использовал для преобразования имен PascalCase для подчеркивания имен. Он включает соглашение для свойств id ... Он также включает дополнительный префикс имени таблицы.

public class UnderscoreNamingConvention : IConfigurationConvention<PropertyInfo, PrimitivePropertyConfiguration>,
                                          IConfigurationConvention<Type, ModelConfiguration>
{
    public UnderscoreNamingConvention()
    {
        IdFieldName = "Id";
    }

    public string TableNamePrefix { get; set; }

    public string IdFieldName { get; set; }

    public void Apply(PropertyInfo propertyInfo, Func<PrimitivePropertyConfiguration> configuration)
    {
        var columnName = propertyInfo.Name;

        if (propertyInfo.Name == IdFieldName)
            columnName = propertyInfo.ReflectedType.Name + IdFieldName;

        configuration().ColumnName = ToUnderscore(columnName);
    }

    public void Apply(Type type, Func<ModelConfiguration> configuration)
    {
        var entityTypeConfiguration = configuration().Entity(type);
        if (entityTypeConfiguration.IsTableNameConfigured) return;

        var tableName = ToUnderscore(type.Name);

        if (!string.IsNullOrEmpty(TableNamePrefix))
        {
            tableName = string.Format("{0}_{1}", TableNamePrefix, tableName);
        }

        entityTypeConfiguration.ToTable(tableName);
    }

    public static string ToUnderscore(string value)
    {
        return Regex.Replace(value, "(\\B[A-Z])", "_$1").ToLowerInvariant();
    }
}

Вы используете его так

public class UnderscoreNamingConvention : IConfigurationConvention<PropertyInfo, PrimitivePropertyConfiguration>,
                                          IConfigurationConvention<Type, ModelConfiguration>
{
    public UnderscoreNamingConvention()
    {
        IdFieldName = "Id";
    }

    public string TableNamePrefix { get; set; }

    public string IdFieldName { get; set; }

    public void Apply(PropertyInfo propertyInfo, Func<PrimitivePropertyConfiguration> configuration)
    {
        var columnName = propertyInfo.Name;

        if (propertyInfo.Name == IdFieldName)
            columnName = propertyInfo.ReflectedType.Name + IdFieldName;

        configuration().ColumnName = ToUnderscore(columnName);
    }

    public void Apply(Type type, Func<ModelConfiguration> configuration)
    {
        var entityTypeConfiguration = configuration().Entity(type);
        if (entityTypeConfiguration.IsTableNameConfigured) return;

        var tableName = ToUnderscore(type.Name);

        if (!string.IsNullOrEmpty(TableNamePrefix))
        {
            tableName = string.Format("{0}_{1}", TableNamePrefix, tableName);
        }

        entityTypeConfiguration.ToTable(tableName);
    }

    public static string ToUnderscore(string value)
    {
        return Regex.Replace(value, "(\\B[A-Z])", "_$1").ToLowerInvariant();
    }
}

EDIT : в вашем случае метод Apply должен выглядеть примерно так:

public class UnderscoreNamingConvention : IConfigurationConvention<PropertyInfo, PrimitivePropertyConfiguration>,
                                          IConfigurationConvention<Type, ModelConfiguration>
{
    public UnderscoreNamingConvention()
    {
        IdFieldName = "Id";
    }

    public string TableNamePrefix { get; set; }

    public string IdFieldName { get; set; }

    public void Apply(PropertyInfo propertyInfo, Func<PrimitivePropertyConfiguration> configuration)
    {
        var columnName = propertyInfo.Name;

        if (propertyInfo.Name == IdFieldName)
            columnName = propertyInfo.ReflectedType.Name + IdFieldName;

        configuration().ColumnName = ToUnderscore(columnName);
    }

    public void Apply(Type type, Func<ModelConfiguration> configuration)
    {
        var entityTypeConfiguration = configuration().Entity(type);
        if (entityTypeConfiguration.IsTableNameConfigured) return;

        var tableName = ToUnderscore(type.Name);

        if (!string.IsNullOrEmpty(TableNamePrefix))
        {
            tableName = string.Format("{0}_{1}", TableNamePrefix, tableName);
        }

        entityTypeConfiguration.ToTable(tableName);
    }

    public static string ToUnderscore(string value)
    {
        return Regex.Replace(value, "(\\B[A-Z])", "_$1").ToLowerInvariant();
    }
}

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

Попробуйте это в своем классе DbContext;

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<int>()
      .Where(p => p.Name.Equals("Id"))
      .Configure(c => c.HasColumnName(c.ClrPropertyInfo.ReflectedType.Name + "Id"));
}

int - это тип полей моего основного ключа CLR. Я хочу ссылаться на все ключи в коде как Id, но для ключей DBA требуются идентификаторы с префиксом имени сущности таблицы. Выше дает мне именно то, что я хочу в моей созданной базе данных.

Требуется Entity Framework 6.x.




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