Bueno, lo prometido es deuda, y como a muchos “amiguetes” les prometí no abandonar la serie sobre mapping de EF 4.1 puest aquí sigo al ataque. Se que alguno me recordará que también tengo pendiente escribir el apéndice sobre EF 4.1 que permita completar el libro de EF que acabo de publicar, con respecto a esto, me gustaría, aprovechando la coyuntura hacer dos anotaciones. La primera es que más que un apéndice-capítulo se está convirtiendo casi en un libro aparte, el caso es que son tantas cosas para contar que uno va degenerando en páginas y páginas, espero que provechosas. Le segunda anotación que me gustaría hacer es que trataré por todos los medios que aquellos que habéis comprado el libro podáis acceder a este apendice/nuevo libro de una forma “nada” costosa.
Venga al tajo, la idea con este y algún nuevo post, es ir ampliando la información sobre mapping o bien creando código que nos ayude con este trabajo. La idea de hacerlo un poco más cañero de lo normal viene del hecho que últimamente he leído algún post como este de José Ramaniello que me ha parecido bastante un poco sesgado y, por lo tanto, aquí estamos.
En ocasiones podemos encontrarnos escenarios dónde necesitemos que nuestras entidades puedan mapear una propiedad no pública, si, has escuchado bien. El ejemplo más prototípico de esto es por ejemplo en un agregado raiz ocultar el acceso directo a una navegación, de tal forma que, las operaciones de agregar entidades al agregado se puedan hacer por medio de un método del mismo y no directamente por una colección. Cierto es, que por defecto EF 4.1 no nos permite el mapeo de elementos privados, por lo menos en la superficie del API, sin embargo, rebuscando un poco y no conformándose es medianamente sencillo ver que tenemos solución a este problema. Realmente, cuando mapeamos una propiedad escribimos algo similar a lo siguiente:
1 2 3 4 5 6 |
<span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Customer>() .Property(p => p.FirstName) .HasMaxLength(200); } |
Pues bien, el método Property, que admite una expresión lambda, realmente no tiene porque circunscribirse a propiedades públicas, es decir, podríamos crear, gracias a las capacidades de los árboles de expressiones, una firma idéntica a la solicitada por este método sin necesidad de que el acceso fuera a un elemento público, ¿como? Pues bien, en el siguiente método extensor podéis ver como generar un nuevo método Property con esta capacidad.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<span class="rem">/// <summary></span> <span class="rem">/// Extension method for map private properties</span> <span class="rem">/// <example></span> <span class="rem">/// modelBuilder.Entity{Customer}()</span> <span class="rem">/// .Property{Customer,int}("Age")</span> <span class="rem">/// .IsOptional()</span> <span class="rem">/// </example></span> <span class="rem">/// </summary></span> <span class="rem">/// <typeparam name="TEntityType">The type of entity to map</typeparam></span> <span class="rem">/// <typeparam name="KProperty">The type of private property to map</typeparam></span> <span class="rem">/// <param name="entityConfiguration">Asociated EntityTypeConfiguration</param></span> <span class="rem">/// <param name="propertyName">The name of private property</param></span> <span class="rem">/// <returns>A PrimitivePropertyConfiguration for this map</returns></span> <span class="kwrd">public</span> <span class="kwrd">static</span> PrimitivePropertyConfiguration Property<TEntityType, KProperty>(<span class="kwrd">this</span> EntityTypeConfiguration<TEntityType> entityConfiguration, <span class="kwrd">string</span> propertyName) <span class="kwrd">where</span> TEntityType : <span class="kwrd">class</span> <span class="kwrd">where</span> KProperty:<span class="kwrd">struct</span> { var propertyInfo = <span class="kwrd">typeof</span>(TEntityType).GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); <span class="kwrd">if</span> ( propertyInfo != <span class="kwrd">null</span> ) <span class="rem">// if private property exists</span> { ParameterExpression arg = Expression.Parameter(<span class="kwrd">typeof</span>(TEntityType), <span class="str">"parameterName"</span>); MemberExpression memberExpression = Expression.Property((Expression)arg, propertyInfo); <span class="rem">//Create the expression to map</span> Expression<Func<TEntityType, KProperty>> expression = (Expression<Func<TEntityType, KProperty>>)Expression.Lambda(memberExpression, arg); <span class="kwrd">return</span> entityConfiguration.Property(expression); } <span class="kwrd">else</span> <span class="kwrd">throw</span> <span class="kwrd">new</span> InvalidOperationException(<span class="str">"The property not exist"</span>); } |
Ahora, gracias a este método extensor podríamos escribir mapeos con el siguiente:
1 2 3 4 5 6 |
<span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Customer>() .Property<Customer,<span class="kwrd">int</span>>(<span class="str">"PrivateMember"</span>); } |
1 |
<font color="#333333" face="Verdana">Y ahora que sigue? pues os pido que a los que os guste jugar que is esto mismo para las propiedades de . </font> |
¿Os ha gustado? Pues esto, y muchas cosas más ya están la cocina del nuevo apéndice-capitulo, perdón por la promoción :-/, algunas, para abrir bocar y quizás, para cerrar alguna, las iremos poniendo en sucesivas entradas.
1 |
<font color="#333333" face="Verdana"></font> |
1 |
|
1 |
<font color="#333333" face="Verdana">Saludos</font> |
1 |
<font color="#333333" face="Verdana">Unai</font> |
1 |
The klingon note: Debugging? Klingons do not debug. Bugs are good for building character in the user! |
1 |
<font color="#333333" face="Verdana"></font> |