Default value for property according to type and core

0

I have a code in which I define some properties according to the type of the variable in EF6

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties().Where(p => p.Name == p.ReflectedType.Name + "Id").Configure(p => p.IsKey());

    modelBuilder.Properties<string>().Configure(p => p.HasColumnType("varchar"));

    modelBuilder.Properties<string>().Configure(p => p.HasMaxLength(50));
}

How to configure these properties according to the EF Core type?

    
asked by anonymous 28.03.2018 / 14:27

1 answer

2

EF Core does not have such a method, however you can extend ModelBuilder to gain this functionality.

At one time, I needed to configure the properties of a particular interface. But as you might guess, builder.Entity<T> does not accept Interface as the first argument.

Then I implemented the following method in a static class :

public static void Entities<T>(this ModelBuilder builder, DbContext instance, string methodName)
{
    var method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic);
    var typesStatus = builder.Model.GetEntityTypes().Where(type => typeof(T).IsAssignableFrom(type.ClrType));
    foreach (var type in typesStatus)
    {
        var builderType = typeof(EntityTypeBuilder<>).MakeGenericType(type.ClrType);
        var buildMethod = method.MakeGenericMethod(type.ClrType);
        var buildAction = typeof(Action<>).MakeGenericType(builderType);
        var buildDelegate = Delegate.CreateDelegate(buildAction, instance, buildMethod);
        var buildEntity = typeof(ModelBuilder).GetMethods()
            .Single(m => m.Name == "Entity" && m.GetGenericArguments().Any() && m.GetParameters().Any())
            .MakeGenericMethod(type.ClrType);

        buildEntity.Invoke(builder, new[] { buildDelegate });
    }
}

The call to this method was something like.:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entities<IInterfaceA>(this, nameof(this.ModelInterfaceA));
    builder.Entities<IInterfaceB>(this, nameof(this.ModelInterfaceB));
}

private void ModelInterfaceA<T>(EntityTypeBuilder<T> entity) where T : class, IInterfaceA
{
    entity.HasQueryFilter(x => x.Ativo);
    entity.Property(x => x.Data).HasColumnType("datetime2(2)");
}

private void ModelInterfaceB<T>(EntityTypeBuilder<T> entity) where T : class, IInterfaceB
{
    entity.Property(x => x.Property).HasColumnType("...");
}

Modifying the extension to work with properties.

For your specific case, I will make an adaptation of the above mentioned method:

public static void Properties<T>(this ModelBuilder builder, Action<PropertyBuilder<T>> callback)
{
    var types = builder.Model.GetEntityTypes();
    foreach (var type in types)
    {
        var entityBuilderType = typeof(EntityTypeBuilder<>).MakeGenericType(type.ClrType);

        var buildEntity = typeof(ModelBuilder).GetMethods()
            .Single(m => m.Name == "Entity" && m.GetGenericArguments().Any() && !m.GetParameters().Any())
            .MakeGenericMethod(type.ClrType);

        var buildProperty = entityBuilderType.GetMethods()
            .Single(m => m.Name == "Property" && m.GetGenericArguments().Any() && m.GetParameters().Any(p => p.ParameterType == typeof(string)))
            .MakeGenericMethod(type.ClrType);

        var entityTypeBuilder = buildEntity.Invoke(builder, null);
        var properties = type.GetProperties().Where(x => x.GetType().Equals(typeof(T)));
        foreach (var property in properties)
        {
            var propertyBuilder = buildProperty.Invoke(entityTypeBuilder, new[] { property.Name }) as PropertyBuilder<T>;
            callback(propertyBuilder);
        }
    }
}

Using it is even simpler.:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Properties<string>(config => {
        config.HasColumnType("varchar(50)");
    })
}

The above method has not been tested, in any case, you can use the original algorithm to hone or correct the suggested fix.

    
28.03.2018 / 15:11