как применить общую конфигурацию ко всем объектам в ядре ef - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть сущности, полученные из базовой сущности в моем приложении, которая использует базовый подход ef core.

Базовый класс

public abstract class BaseEntity<T> : IEntity<T>
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public T Id { get; set; }

    object IEntity.Id { get { return Id; } set { } }

    private DateTime? createdOn;
    [DataType(DataType.DateTime)]
    public DateTime CreatedOn { get => createdOn ?? DateTime.Now; set => createdOn = value; }

    [DataType(DataType.DateTime)]
    public DateTime? ModifiedOn { get; set; }

    public bool IsDeleted { get; set; }
    // Auto increment for all entities.
    public int OrderId { get; set; }
}

И субъект

public class UserEntity : BaseEntity<int>
{
    public string EmployeeId { get; set; }
    public string FullName { get; set; }
    public string Email { get; set; }
}

Я могу применить метод .ValueGeneratedOnAdd() к свойству OrderId в OnModelCreating для каждой сущности однако есть ли способ применить общее правило ко всем сущностям без повторения себя?

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

В EF6 вы можете использовать:

modelBuilder.Properties<int>().Where(p=>p.Name == "OrderId").Configure(c => c.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity));
0 голосов
/ 15 ноября 2018

При отсутствии пользовательских соглашений вы можете использовать типичный цикл modelBuilder.Model.GetEntityTypes(), определить типы целевых объектов и вызвать общую конфигурацию.

Идентификация в вашем случае немного сложна из-за базового универсального класса, но выполнимо путем итерации вниз Type.BaseType и проверки на BaseEntity<>. Найдя его, вы можете получить общий аргумент T, который понадобится вам позже.

Если вы не хотите использовать универсальный класс, реализующий IEnityTypeConfiguration<TEntity>, то идея состоит в том, чтобы поместить реализацию в универсальный ограниченный метод, подобный этому

static void Configure<TEntity, T>(ModelBuilder modelBuilder)
    where TEntity : BaseEntity<T>
{
    modelBuilder.Entity<TEntity>(builder =>
    {
        builder.Property(e => e.OrderId).ValueGeneratedOnAdd();
    });
}

Передача фактического типа объекта TEntity в modelBuilder.Enity метод имеет решающее значение, потому что в противном случае EF Core будет считать все, что вы передаете, типом объекта и сконфигурировать наследование TPH.

Вызов метода требует отражения - поиск определения общего метода с использованием MakeGenericMethod, а затем Invoke.

Вот все, что заключено в статический класс:

public static class BaseEntityConfiguration
{
    static void Configure<TEntity, T>(ModelBuilder modelBuilder)
        where TEntity : BaseEntity<T>
    {
        modelBuilder.Entity<TEntity>(builder =>
        {
            builder.Property(e => e.OrderId).ValueGeneratedOnAdd();
        });
    }

    public static ModelBuilder ApplyBaseEntityConfiguration(this ModelBuilder modelBuilder)
    {
        var method = typeof(BaseEntityConfiguration).GetTypeInfo().DeclaredMethods
            .Single(m => m.Name == nameof(Configure));
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            if (entityType.ClrType.IsBaseEntity(out var T))
                method.MakeGenericMethod(entityType.ClrType, T).Invoke(null, new[] { modelBuilder });
        }
        return modelBuilder;
    }

    static bool IsBaseEntity(this Type type, out Type T)
    {
        for (var baseType = type.BaseType; baseType != null; baseType = baseType.BaseType)
        {
            if (baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(BaseEntity<>))
            {
                T = baseType.GetGenericArguments()[0];
                return true;
            }
        }
        T = null;
        return false;
    }
}

Теперь все, что вам нужно, это позвонить изнутри вашего OnModelCreating переопределения:

modelBuilder.ApplyBaseEntityConfiguration();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...