1

The answer for this question (link below) lead me to wonder if my question is possible?

Entity Framework Code First fluent API setting field properties in a for loop

Is there a way to do this more dynamically? I have multiple models I want to do this with and do not want to clone the code in onmodelcreating for each entity class I want to configure. Possibly an empty base class?

Community
  • 1
  • 1
Shawn
  • 869
  • 1
  • 9
  • 27

1 Answers1

2

In EF6 you would do this with custom conventions. Should be no more than a couple lines of code.

In EF5 you would probably have to discover your entity types using reflection and then configure them as described in the link you provided above. Here is the code I came up with (I stole the method for building expression for accessing the property from the post you linked above):

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    foreach (var contextProperty in typeof(Context).GetProperties())
    {
        if (contextProperty.PropertyType.IsGenericType && 
            contextProperty.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
        {
            var entityType = contextProperty.PropertyType.GenericTypeArguments[0];

            foreach(var decimalProperty in entityType.GetProperties().Where(p => p.PropertyType == typeof(decimal)))
            {    
                var configurePropertyMethod = 
                    GetType()
                    .GetMethod("ConfigureProperty", BindingFlags.Static | BindingFlags.NonPublic)
                    .MakeGenericMethod(entityType);
                configurePropertyMethod.Invoke(null, new object[] { modelBuilder, decimalProperty });
            }
        }
    }
}

private static void ConfigureProperty<T>(DbModelBuilder modelBuilder, PropertyInfo propertyInfo) 
    where T : class
{
    var propertyExpression = BuildLambda<T, decimal>(propertyInfo);
    modelBuilder.Entity<T>().Property(propertyExpression).HasPrecision(10, 3);
}

private static Expression<Func<T, U>> BuildLambda<T, U>(PropertyInfo property)
{
    var param = Expression.Parameter(typeof(T), "p");
    MemberExpression memberExpression = Expression.Property(param, property);
    var lambda = Expression.Lambda<Func<T, U>>(memberExpression, param);
    return lambda;
}
Community
  • 1
  • 1
Pawel
  • 31,342
  • 4
  • 73
  • 104
  • What about EF 5, my understanding is EF 6 is still in beta? – Shawn Oct 10 '13 at 02:05
  • In EF5 you would have to take the Reflection route as it was shown in the post you linked. Regarding EF6 being in Beta - VS2013 RC is a "go live" release and EF6 is part of it. Final EF6 release will be shipped with VS2013 which according to this http://www.zdnet.com/microsoft-delivers-near-final-visual-studio-2013-release-candidate-7000020423/ is supposed to be soon. – Pawel Oct 10 '13 at 02:42
  • That's the problem I'm having. I am not a reflection/generics expert so I'm having trouble figuring out how to pull this off. – Shawn Oct 11 '13 at 00:05
  • @Shawn - I updated the response with a full code sample. Hope this helps. – Pawel Oct 14 '13 at 17:13
  • 1
    @Shawn - EF6 RTM'd today along with Visual Studio 2013 so you know should be able to take advantage of custom conventions. – Pawel Oct 17 '13 at 17:00
  • I'll probably stick with EF 5 simply because swapping out for 6 would require a lot of retesting for the project I'm working on. Thanks for all the help though! – Shawn Oct 18 '13 at 01:30