Map private properties with EF Fluent API

Map private properties with EF Fluent API

Rate This
  • Comments 3

So until we get EF 4.2 and the support for enumerations as first class citizens those of us needing support have resigned ourselves to the simple fact that we are forced to expose a property for the integer value for EF to use and wrap that value with a convenience property that casts it as the appropriate enumeration. There are additional tricks that people have supplied for easing use of enums (check out Alex’s fun approach here).

Now for the brave, they’ve discovered that EF actually doesn’t care about visibility of the property setter. It can be private if you want it to be. Of course if you are using the designer you need to simply set the visibility of the properties as appropriate and life is good. However those of you using the code only Fluent API will note that it is tied completely to mapping properties via expressions and usually those same expressions are written in another class, a class that may or may not be even in the same assembly. This makes working on mapping private properties a bit of a pain. Well here’s a simple set of extension methods that can use that will accept a string parameter for the property name and using a wee bit of reflection will build up the exact same expression that EF expects.

public static class EntityConfigurationExtensions
{
    private static Expression<Func<T, K>> CreateExpression<T, K>(String propertyName)
    {
        var type = typeof(T);
        var arg = Expression.Parameter(type, "x");
        Expression expr = arg; 

        var pi = type.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

        if (pi == null) throw new ArgumentException(String.Format("Property '{0}' on type '{1}' cannot be found.", propertyName, type.FullName));

        expr = Expression.Property(expr, pi);

        LambdaExpression lambda = Expression.Lambda(expr, arg);

        var expression = (Expression<Func<T, K>>)lambda;

        return expression;
    }

    public static StringPropertyConfiguration Property<T>(this EntityTypeConfiguration<T> mapper, String propertyName) where T : class
    {
        var expression = CreateExpression<T, String>(propertyName);

         return mapper.Property(expression);
   } 

    public static PrimitivePropertyConfiguration Property<T, K>(this EntityTypeConfiguration<T> mapper, String propertyName)

        where T : class

        where K : struct
    {
        var expression = CreateExpression<T, K>(propertyName);

        return mapper.Property(expression);
    }
}

This should give you a simple time now of hiding your EF required gunk that leaks into your domain models so that at least it isn't visible outside the entities in question. Of course all this isn't actually needed after 4.2, or so they say...

Comments
  • Thank you for the code. Now how do we use it?

  • I am going to assume a certain level of EF proficiency here but image a class that has three properties on it.

    Id as Int32, Status as some enum you've defined (say Active, Locked, Deleted), and a property that you need to use for EF support that has the integer value for the status in the DB. Since you cannot map enum values yet to EF you are forced to have this property and that's what EF will be made to map. You can make the property private and configure the mapping as such in your EntityTypeConfiguration<T> class:

    this.Property<MyEntity, Int32>("MyPrivateProperty").HasColumnName("Foo");

    That's it.

    There's a specific overload specially for string mapping that's used like this instead (since you don't need to specifiy the return type):

    this.Property("MyPrivateStringProperty").HasColumnName("FooString");

  • I see now. I thought I had to pass this off to a mapping function initially. You're awesome and saved me from a pretty nasty alternative!

Page 1 of 1 (3 items)
Leave a Comment
  • Please add 7 and 5 and type the answer here:
  • Post