EF 4.1 is now in RC phase and as a NHibernate user I’m curious to check the fluent API to map entities to database. One of the feature that I and Andrea miss most is the possibility to map private properties with fluent interface. It seems strange to map private properties at once, but it can be useful in DDD. Suppose you have these simple classes.
Figure 1: A really simple domain
We have two things to notice, the first is that the Category class has a private property called PrivateDetails, and the other is that the Products collection is protected, and you can add products from the outside thanks to the AddProduct() method.
The idea behind this is that you should access only the AGGREGATE roots, not manipulating directly the collection of Products, this forces the user of the class to use specific methods. Now a problem arise, how we can map this class with EF 4.1 fluent interface? The problem is generated from the Fluent interface, that permits only to specify properties with Lambda.
Figure 2: The HasMany() method accepts an Expression
As you can see if I specify that CategoryId is mapped to an Identity database column with the instruction
Property(c => c.CategoryId)
this technique is known as static reflection and is really useful in such scenarios, but … now I could not use the HasMany() methods to map a protected property.
Figure 3: How can I map a protected property if I could not use in a lambda?
This problem derives only from the Fluent Interface, because EF is internally capable to map private members of objects, then we can use a little trick. I want to be able to write code like this
This would solve all our problems, because with this statement I’m asking EF to map a collectino called Products. Fortunately writing such an extension method is quite simple, it is just a bunch of Expressions
This code seems complex but it is rather simple. It creates a parameter expression of the same type of the object, then grab a reference to the property from its name with reflection and with the PropertyInfo creates an Expression.Property. This expression (created in line 13) is the equivalent of c => c.Products lambda and it can be passed to the Expression.Lambda to create an Expression<Func<T, ICollection<U>>> object, expected from the HasMany() method.
With the same technique I can write an extension method that maps a private string property.
Thanks to those two methods now I’m able to write this mapping for the category class.
As you can see I’m able to map the PrivateDetails property and I can choose column name, and the Products property with no problem. Now I can use my model
As you can ses I’m able to add product without the need to directly access the collection, and I can set a private property through a method (not so useful technique, but just to show that mapping private properties works). Running the sample I got
Figure 4: The fact that three entities were saved confirmed me that the mapping of the protected collection works.
I can verify that everything is ok thanks to EFProfiler.
Figure 5: Thanks to EFProf I can verify that products are correctly saved and linked to the category object
EF 4.1 Code first finally gives to EF the direction towards a real ORM, usable in DDD scenario.