Map private properties with EF Fluent API
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
Anonymous
October 05, 2011
Thank you for the code. Now how do we use it?Anonymous
October 06, 2011
The comment has been removedAnonymous
October 07, 2011
The comment has been removed