Entity Framework 4.2 http://blogs.ugidotnet.org/PietroLibroBlog/category/Entity Framework 4.2.aspx Entity Framework 4.2 it-IT Pietro Libro pietro.libro@libero.it Subtext Version 2.6.0.0 EF Power Tools Beta 2: Prove su strada http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/04/11/ef-power-tools-beta-2-prove-su-strada.aspx <p>Ero troppo curioso di provare la nuova versione (beta) dei Tools per EF. Diciamo che la curiosità è stata parzialmente ripagata <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/wlEmoticon-smile_2.png" /> dato che con la prima versione non riuscii  a fare granché essendo, almeno nella mia configurazione software, non molto stabile. Andiamo con ordine: dopo aver installato la nuova versione dei Tools, ho provato subito ad eseguire la funzione “Reverse Engineer Code First”  (disponibile come voce di menu contestuale selezionando un progetto C#).</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_2.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb.png" width="293" height="128" /></a></p> <p>Per l’esperimento ho scelto un database con diverse tabelle, relazioni e “gerarchie”. Dopo aver cliccato sulla voce precedente, VS ha iniziato a “macinare” generando una sfilza di classi, suddividendole opportunatamente in classi di <em>Mapping</em>, <em>Object Model</em> e <em>DbContext</em>:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_4.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb_1.png" width="179" height="244" /></a></p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_6.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb_2.png" width="244" height="205" /></a></p> <p>L’operazione è durata pochi secondi. Secondo il post del team di ADO.NET EF, VS avrebbe dovuto scaricare ed installare (se non già presente nel progetto) l’ultima versione di Entity Framework (nello specifico caso non è accaduto, ma con NuGet, anche questa operazione è durata poco <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/wlEmoticon-smile_2.png" /> ). Scorrendo l’elenco delle classi generate noto come il processo di <em>reverse engineering </em>abbia creato delle classi anche per le tutte le viste presenti sul database. Proviamo ad analizzare “graficamente” il modello ad oggetti creato, selezionando nel <em>Solution Explorer </em>la classe derivata dal <em>DbContext</em> e poi la voce “View Entity Data Model (Read Only)”:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_8.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb_3.png" width="244" height="154" /></a></p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_12.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb_5.png" width="244" height="209" /></a></p> <p>Molte delle classi “isolate” sono proprio le classi\viste generate dal VS. Con le altre opzioni disponibili possiamo, creare il DDL SQL:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_14.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb_6.png" width="244" height="130" /></a></p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_16.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb_7.png" width="244" height="241" /></a></p> <p>e visualizzare <em>l’Entity Data Model XML</em>:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_18.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb_8.png" width="244" height="142" /></a></p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_20.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb_9.png" width="244" height="131" /></a></p> <p>Se siamo curiosi, possiamo creare un nuovo database a partire dalle classi generate da VS e poi eseguire uno <em>Schema Compare</em> per visionare le differenze tra l’originale ed il generato:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_22.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/image_thumb_10.png" width="244" height="79" /></a></p> <p> </p><p>A colpo d’occhio mancano, rispetto all’originale, Stored Procedure e Viste, poi analizzando nel dettaglio le varie tabelle possiamo trovare alcune differenze come VARCHAR in NVARCHAR, valori di default mancanti, campi TEXT trasformati in NVARCHAR(MAX). Riassumendo, i Tools sembrano essere abbastanza stabili (rispetto alla versione precedente nessun crash <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/c2771568168c_12AC0/wlEmoticon-smile_2.png" />) , quello che è certo (almeno fino ad ora) che dovendo partire da un database esistente, sviluppare le classi POCO e <em>DbContext</em> con questa rapidità non ha prezzo, ma sicuramente è necessario un ulteriore lavoro di “fino” (magari in combinazione con EF Code First Migrations) se l’obiettivo è quello di avere un modello finale “fedele” all’originale, in caso contrario è un ottima base di partenza per un <em>refactoring</em>.</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100945.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/04/11/ef-power-tools-beta-2-prove-su-strada.aspx Wed, 11 Apr 2012 07:53:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/04/11/ef-power-tools-beta-2-prove-su-strada.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100945.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100945.aspx DomusDotNet : We Want Web, grazie a tutti :-) http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/03/10/domusdotnet-wewantweb-grazie-a-tutti.aspx <p>Ieri 9/3/12 si è svolto l’evento WeWantWeb organizzato da DomusDotNet presso la sede Microsoft di Roma. Le sessioni sono state registrare e quanto prima pubblicheremo Slide, codice sorgente degli esempi e Video, sul sito di <a href="http://www.domusdotnet.org/" target="_blank">DomusDotNet</a>. Grazie a tutti i partecipanti!!! Attendiamo i vostri feedback! Al prossimo evento <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/wlEmoticon-smile_2.png" />.</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000309_2.jpg"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Alessandro Mostarda e Massibo Bonanni" border="0" alt="Alessandro Mostarda e Massibo Bonanni" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000309_thumb.jpg" width="184" height="244" /></a><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000311_2.jpg"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Giorgio Di Nardo" border="0" alt="Giorgio Di Nardo" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000311_thumb.jpg" width="184" height="244" /></a><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000317_2.jpg"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Nicolò Carandini" border="0" alt="Nicolò Carandini" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000317_thumb.jpg" width="184" height="244" /></a><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000333_2.jpg"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Pietro Libro" border="0" alt="Pietro Libro" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000333_thumb.jpg" width="184" height="244" /></a><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000307_2.jpg"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="WP_000307" border="0" alt="WP_000307" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/WP_000307_thumb.jpg" width="184" height="244" /></a></p> <p>Da sinistra verso destra: <a href="http://www.alessandromostarda.com/" target="_blank">Alessandro Mostarda</a> e <a href="http://codetailor.blogspot.com/" target="_blank">Massimo Bonanni</a>, Giorgio Di Nardo, <a href="http://blogs.ugidotnet.org/Nick60/Default.aspx" target="_blank">Nick</a>, io <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/wlEmoticon-smile_2.png" />, parte di coloro che hanno avuto la pazienza di ascoltarci <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/7226c6221ecf_11545/wlEmoticon-smile_2.png" />.</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100854.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/03/10/domusdotnet-wewantweb-grazie-a-tutti.aspx Sat, 10 Mar 2012 20:52:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/03/10/domusdotnet-wewantweb-grazie-a-tutti.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100854.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100854.aspx DomusDotNet: WCF Data Services (Seconda Parte) http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/11/domusdotnet-wcf-data-services-seconda-parte.aspx <p>Secondo articolo della serie dedicata ai WCF Data Services: utilizzo con Entity Framework, ed approfondimento su Service Operations. Nel codice allegato un client ASP.NET MVC di test. Articolo completo sul sito di <a href="http://www.domusdotnet.org/articoli/wcf-data-services-%28parte-2%29.aspx" target="_blank">DomusDotNet</a>. Al solito, consigli e suggerimenti sono sempre ben accetti <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/DomusDotNet-WCF-Data-Services-Seconda-Pa_60A5/wlEmoticon-smile_2.png" />.</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100692.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/11/domusdotnet-wcf-data-services-seconda-parte.aspx Wed, 11 Jan 2012 07:56:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/11/domusdotnet-wcf-data-services-seconda-parte.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100692.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100692.aspx Expression, LambdaExpression, Entity Framework (e DDD) http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/11/10/expression-lambdaexpression-entity-framework-e-ddd.aspx <p>Se lavoriamo con EF utilizzando l’approccio Code First, in alcuni scenari,  il <em>mapping</em> (ad esempio nel caso di classi di dominio già esistenti) potrebbe essere un task non banale. Riprendiamo un esempio di <a href="http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/04/04/ef-code-first-e-ddd.aspx" target="_blank">qualche tempo fa</a> , aggiungendo all’Object Model l’entità <em>Articolo</em>, come riassunto dal Class Diagram seguente:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Expression-Lambda-Entity-Framework_5A2F/image_2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Expression-Lambda-Entity-Framework_5A2F/image_thumb.png" width="359" height="152" /></a></p> <p><em>Fattura </em>espone una collezione di oggetti <em>RigoFattura  </em>accessibile (dall’esterno) tramite <em>l’IEnumerable&lt;RigoFattura&gt;  </em>pertanto, l’unico modo di aggiungere nuove righe alla fattura è l’utilizzo del metodo <em>AddRigoFattura</em>. Ancora, la classe <em>RigoFattura </em>contiene una proprietà <em>CodiceArticolo </em>che ritorna la proprietà <em>Codice </em>dell’istanza della classe <em>Articolo </em>referenziata, ma anche in questo caso, l’unico modo per aggiungere un Articolo  è tramite un metodo : <em>ImpostaArticolo</em>.  A questo punto qualcuno potrebbe dire, “Si ok, ma dov’è il problema ?” Come descritto nel post precedente, durante il <em>mapping, </em>nell’<em>override </em>dell’<em>OnModelBuilder</em>, abbiamo qualche problema in fase di compilazione:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Expression-Lambda-Entity-Framework_5A2F/image_4.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Expression-Lambda-Entity-Framework_5A2F/image_thumb_1.png" width="347" height="161" /></a></p> <p>Questo perché le Fluent API, come è facile intuire, non vanno d’accordo con i membri <em>Protected </em>(o comunque non accessibili dall’esterno)<em>.</em> In questi casi, la soluzione che possiamo adottare è quella di creare una serie di <em>Extension Methods </em>che basandosi sul nome delle Proprietà e Navigation Properties ci permettano di creare delle espressioni da poter utilizzare nel nostro scenario di <em>mapping</em>:</p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> Methods { <span class="kwrd">private</span> <span class="kwrd">static</span> Expression&lt;Func&lt;T, K&gt;&gt; CreateExpression&lt;T, K&gt;(String propertyName) { Type type = <span class="kwrd">typeof</span>(T); PropertyInfo pi = type.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); <span class="kwrd">if</span> (pi == <span class="kwrd">null</span>) <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException(<span class="str">"propertyName is not valid."</span>); ParameterExpression argumentExpression = Expression.Parameter(type, <span class="str">"x"</span>); MemberExpression memberExpression = Expression.Property(argumentExpression, pi); LambdaExpression lambda = Expression.Lambda(memberExpression, argumentExpression); Expression&lt;Func&lt;T, K&gt;&gt; expression = (Expression&lt;Func&lt;T, K&gt;&gt;)lambda; <span class="kwrd">return</span> expression; } <span class="kwrd">public</span> <span class="kwrd">static</span> PrimitivePropertyConfiguration Property&lt;TEntity, KPropertyType&gt;(<span class="kwrd">this</span> EntityTypeConfiguration&lt;TEntity&gt; mapper, String propertyName) <span class="kwrd">where</span> TEntity : <span class="kwrd">class</span> <span class="kwrd">where</span> KPropertyType : <span class="kwrd">struct</span> { Expression&lt;Func&lt;TEntity, KPropertyType&gt;&gt; expression = CreateExpression&lt;TEntity, KPropertyType&gt;(propertyName); <span class="kwrd">return</span> mapper.Property(expression); } <span class="kwrd">public</span> <span class="kwrd">static</span> DependentNavigationPropertyConfiguration&lt;TEntity&gt; WithMany&lt;TEntity, KTargetEntity&gt;( <span class="kwrd">this</span> OptionalNavigationPropertyConfiguration&lt;TEntity, KTargetEntity&gt; mapper, String propertyName) <span class="kwrd">where</span> TEntity : <span class="kwrd">class</span> <span class="kwrd">where</span> KTargetEntity : <span class="kwrd">class</span> { Type type = <span class="kwrd">typeof</span>(KTargetEntity); ParameterExpression argumentExpression = Expression.Parameter(type, <span class="str">"x"</span>); PropertyInfo pi = type.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); MemberExpression memberExpression = Expression.Property(argumentExpression, pi); LambdaExpression lambda = Expression.Lambda(memberExpression, argumentExpression); var expression = (Expression&lt;Func&lt;KTargetEntity, ICollection&lt;TEntity&gt;&gt;&gt;)lambda; <span class="kwrd">return</span> mapper.WithMany(expression); } <span class="kwrd">public</span> <span class="kwrd">static</span> RequiredNavigationPropertyConfiguration&lt;TEntity, TTargetEntity&gt; HasRequired&lt;TEntity, TTargetEntity&gt;(<span class="kwrd">this</span> EntityTypeConfiguration&lt;TEntity&gt; mapper, String propertyName) <span class="kwrd">where</span> TEntity : <span class="kwrd">class</span> <span class="kwrd">where</span> TTargetEntity : <span class="kwrd">class</span> { Expression&lt;Func&lt;TEntity, TTargetEntity&gt;&gt; expression = CreateExpression&lt;TEntity, TTargetEntity&gt;(propertyName); <span class="kwrd">return</span> mapper.HasRequired(expression); } <span class="kwrd">public</span> <span class="kwrd">static</span> EntityTypeConfiguration&lt;TEntity&gt; HasKey&lt;TEntity, KKeyType&gt;(<span class="kwrd">this</span> EntityTypeConfiguration&lt;TEntity&gt; mapper, String propertyName) <span class="kwrd">where</span> TEntity : <span class="kwrd">class</span> <span class="kwrd">where</span> KKeyType : <span class="kwrd">struct</span> { Expression&lt;Func&lt;TEntity, KKeyType&gt;&gt; expression = CreateExpression&lt;TEntity, KKeyType&gt;(propertyName); EntityTypeConfiguration&lt;TEntity&gt; m = mapper.HasKey&lt;KKeyType&gt;(expression); <span class="kwrd">return</span> mapper; } <span class="kwrd">public</span> <span class="kwrd">static</span> ManyNavigationPropertyConfiguration&lt;T, U&gt; HasMany&lt;T, U&gt;(<span class="kwrd">this</span> EntityTypeConfiguration&lt;T&gt; mapper, String propertyName) <span class="kwrd">where</span> T : <span class="kwrd">class</span> <span class="kwrd">where</span> U : <span class="kwrd">class</span> { Type type = <span class="kwrd">typeof</span>(T); PropertyInfo pi = type.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); <span class="kwrd">if</span> (pi == <span class="kwrd">null</span>) <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException(<span class="str">"propertyName is not valid."</span>); ParameterExpression parameterExpression = Expression.Parameter(type, <span class="str">"x"</span>); MemberExpression memberExpression = Expression.Property(parameterExpression, pi); LambdaExpression lambda = Expression.Lambda(memberExpression, parameterExpression); Expression&lt;Func&lt;T, ICollection&lt;U&gt;&gt;&gt; expression = (Expression&lt;Func&lt;T, ICollection&lt;U&gt;&gt;&gt;)lambda; <span class="kwrd">return</span> mapper.HasMany(expression); }</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>A questo punto il gioco è facile, definendo il modello in questo modo:</p> <pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity&lt;RigoFattura&gt;(); modelBuilder.Entity&lt;RigoFattura&gt;().ToTable(<span class="str">"RigoFattura"</span>); modelBuilder.Entity&lt;RigoFattura&gt;().Ignore(rf =&gt; rf.CodiceArticolo); modelBuilder.Entity&lt;RigoFattura&gt;().HasRequired&lt;RigoFattura, Articolo&gt;(<span class="str">"Articolo"</span>); modelBuilder.Entity&lt;Fattura&gt;().ToTable(<span class="str">"Fattura"</span>); modelBuilder.Entity&lt;Fattura&gt;().HasKey&lt;<span class="kwrd">int</span>&gt;(f =&gt; f.Numero); modelBuilder.Entity&lt;Fattura&gt;().HasMany&lt;Fattura, RigoFattura&gt;(<span class="str">"RigheFatture"</span>); modelBuilder.Entity&lt;Articolo&gt;().ToTable(<span class="str">"Articoli"</span>); modelBuilder.Entity&lt;Articolo&gt;().HasKey(a =&gt; a.Codice); } </pre> <p /><style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style>Tutto funziona correttamente, e l’esecuzione del codice porta alla corretta creazione del Database come riassunto dal <em>Database Diagram </em>seguente: <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Expression-Lambda-Entity-Framework_5A2F/image_6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Expression-Lambda-Entity-Framework_5A2F/image_thumb_2.png" width="302" height="180" /></a></p> <p>Gli <em>Extension Methods </em>descritti in precedenza, non servono solo a coprire lo scenario descritto nel post, ma anche nel caso di : WithMany, HasKey, HasMany, Property ecc… Aggiungere altri metodi personalizzati è relativamente semplice. Cosa facciamo nel codice: 1) tramite <em>reflection </em>recuperiamo le proprietà che entrano in gioco durante lo scenario di <em>mapping</em> e che non sono visibili dall’esterno 2) Creiamo una <em>ParameterExpression</em> con il tipo entità (TEntity) 3) Creiamo una <em>MemberExpression</em> a partire dalla proprietà ottenuta via <em>reflection</em> e dalla <em>ParameterExpression</em> ottenuta al punto precedente 3) Mettiamo tutto insieme, creiamo una <em>Lambda Expression</em> e da questa una <em>Expression&lt;Func&lt;,&gt;&gt;</em> accettata dal  <em>mapper</em>. In tre “semplici” passi aggiungiamo uno “strato” che ci permette di coprire scenari di <em>mapping </em>“ostici”.</p> <p>Nota bene: questo post non vuole essere in contraddizione con quanto precedentemente scritto a proposito di DDD ed EF, ma presenta solo un <em>workaround</em> per bypassare il problema, ma con tutte le problematiche del caso: di solito le parole “Stringhe” e “Refactoring” non vanno molto d’accordo (se ad esempio cambiamo il nome di una proprietà di una classe, la stringa associata non viene cambiata, creando una “fantastica” eccezione a runtime). Si spera che le prossime release di Entity Framework permettano di risolvere anche questo scoglio. </p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100510.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/11/10/expression-lambdaexpression-entity-framework-e-ddd.aspx Thu, 10 Nov 2011 08:11:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/11/10/expression-lambdaexpression-entity-framework-e-ddd.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100510.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100510.aspx EF 4.2 Released http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/11/02/ef-4.2-released.aspx E' stata rilasciata la versione finale di EF 4.2 contenente aggiornamenti riguardanti il DbContext ed il Code First runtime. L'utilizzo degli Enum, Spatial Data-Type ecc...(<a href="http://blogs.msdn.com/b/adonet/archive/2011/06/30/announcing-the-microsoft-entity-framework-june-2011-ctp.aspx">vedi EF June CTP 2011</a>) non è incluso in questo aggiornamento, in quanto richiederebbe delle modifiche alle librerie del .Net Framework. Il download di EF 4.2 è disponibile via NuGet.<br /> Al solito, per maggiori dettagli: <a href="http://blogs.msdn.com/b/adonet/archive/2011/11/01/ef-4-2-released.aspx">ADO.NET team blog</a>.<img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100488.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/11/02/ef-4.2-released.aspx Wed, 02 Nov 2011 09:21:51 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/11/02/ef-4.2-released.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100488.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100488.aspx