.Net 3.5 http://blogs.ugidotnet.org/Crad/category/.Net 3.5.aspx .Net 3.5 it-IT Marco De Sanctis Subtext Version 2.6.0.0 LINQ to Sql e Guid autogenerati http://blogs.ugidotnet.org/Crad/archive/2008/05/06/linq-to-sql-e-guid-autogenerati.aspx <p>Durante la realizzazione del layer di accesso ai dati di una semplice demo app, per il quale avevo scelto di utilizzare LINQ to Sql, sono incorso in un noioso bug nel recupero dei valori delle PrimaryKey, nel caso in cui questi siano autogenerati dal server di database.</p> <p>Supponiamo di avere una tabella del tipo seguente, in cui la PK sia di tipo <em>uniqueidentifier</em>, automaticamente inizializzata per le nuove righe tramite la funzione di sistema <em>newid()</em>:</p> <p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="198" alt="image" src="http://www.marcodesanctis.it/images/Blog/BugdiLinqToSql_9A8F/image.png" width="274" border="0" /> </p> <p>Creiamo un nuovo DataContext di LINQ to Sql e importiamo al tabella creata; il designer crea una nuova entity con i campi omonimo delle colonne sul database:</p> <p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="119" alt="image" src="http://www.marcodesanctis.it/images/Blog/BugdiLinqToSql_9A8F/image11.png" width="204" border="0" /> </p> <p>Spesso, lato schema DB, i nomi delle chiavi contengono un riferimento alla tabella a cui appartengono. Per quanto riguarda le entità di dominio, invece, preferisco che gli identificativi si chiamino tutti allo stesso modo, sia per una questione di uniformità e leggibilità (non essendoci FK ma semplici riferimenti, non ho più la necessità di avere nomi diversi), sia perchè, ad esempio, potrei pensare di far implementare a tutte le mie entity un'interfaccia <em>IHasIdentifier</em> che esponga la proprietà <em>Id</em> e utilizzarla per implementare un GetById generico. Quindi, forte delle mie convinzioni, procedo alla modifica sulla entità di L2S generata dal designer:</p> <p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="120" alt="image" src="http://www.marcodesanctis.it/images/Blog/BugdiLinqToSql_9A8F/image14.png" width="205" border="0" /> </p> <p>Inoltre, mi ricordo anche di impostare, sulla property grid, che la proprietà Id è auto generata da DB e che deve essere recuperata dopo una query di Insert:</p> <p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="174" alt="image" src="http://www.marcodesanctis.it/images/Blog/BugdiLinqToSql_9A8F/image20.png" width="244" border="0" /> </p> <p>In fase di fetch, LINQ to Sql svolge egregiamente il suo lavoro, trasformando correttamente ogni condizione sulla proprietà <em>Id</em> in una where sulla colonna <em>MySampleId</em>:</p> <p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="106" alt="image" src="http://www.marcodesanctis.it/images/Blog/BugdiLinqToSql_9A8F/image_3.png" width="313" border="0" /> </p> <p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="57" alt="image" src="http://www.marcodesanctis.it/images/Blog/BugdiLinqToSql_9A8F/image_4.png" width="405" border="0" /> </p> <p>Ciò purtroppo non accade quando, dopo una query di Insert, L2S tenta di recuperare il valore della chiave generata da database. Come si nota dalla query, infatti, viene erroneamente cercata una colonna chiamata Id, con successivo ed ovvio errore di Sql Server.</p> <p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="78" alt="image" src="http://www.marcodesanctis.it/images/Blog/BugdiLinqToSql_9A8F/image_5.png" width="353" border="0" /></p> <p><a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3289312&amp;SiteID=1">Ho segnalato</a> il problema nei forum di MSDN, e mi è stato risposto che si tratta di un bug che verrà corretto con il rilascio del SP1. Attualmente ci sono solo due soluzioni:</p> <ol> <li>Utilizzare i medesimi nomi per proprietà e colonne</li> <li>Inizializzare manualmente la proprietà ad un nuovo Id sul costruttore della entity</li> </ol> <p>Un'ultima curiosità: tutto ciò non si verifica nel caso in cui la PK sia un Identity e il motivo è che, in quel caso, Linq to Sql utilizza <em>SELECT SCOPE_IDENTITY</em> per recuperare il nuovo valore.</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4c2a6d22-964d-4850-880b-2a968731448d" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/LINQ%20to%20Sql" rel="tag">LINQ to Sql</a></div><img src="http://blogs.ugidotnet.org/Crad/aggbug/92534.aspx" width="1" height="1" /> Marco De Sanctis http://blogs.ugidotnet.org/Crad/archive/2008/05/06/linq-to-sql-e-guid-autogenerati.aspx Tue, 06 May 2008 14:09:22 GMT http://blogs.ugidotnet.org/Crad/archive/2008/05/06/linq-to-sql-e-guid-autogenerati.aspx#feedback 7 http://blogs.ugidotnet.org/Crad/comments/commentRss/92534.aspx Costanti pubbliche? AHIAHIAHI http://blogs.ugidotnet.org/Crad/archive/2008/01/31/costanti-pubbliche-ahiahiahi.aspx <p>Premessa: ciò che scriverò è una banalità, ma secondo me in tanti non ne sono al corrente o non ci pensano. Di cosa parlo? Di cose del genere:</p> <p> </p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:23264bd7-da92-41a5-ba6e-3c35ed74d666" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width:100%;;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">const</span><span style="color: #000000;"> </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> MyConst </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">10</span><span style="color: #000000;">;</span></div></pre></div> <p>Il danno potenziale che le <strong>costanti pubbliche </strong>possono creare alla stabilità delle nostre applicazioni è enorme.</p> <p>Why? Perché le costanti non sono altro che <strong>placeholder</strong> risolti <strong>in fase di compilazione</strong>. Questo vuol dire che, finché non si ricompila, il valore non viene aggiornato.</p> <p>Implicazioni?</p> <ol> <li>Assembly A che definisce una costante MyConst = 10</li> <li>Assembly B che referenzia Assembly A e ne utilizza MyConst</li> <li>Assembly A cambia MyConst a 15</li> <li><strong>Finché non ricompilo Assembly B</strong>, questo continua a vedere MyConst = 10</li></ol> <p>Ogni tanto mi capita di trovare righe di codice simili a quella in alto, con seguenti bug "strani" e dolori per scovarli. Ecco perché cerco sempre di abituare i junior che lavorano con me alla regola:</p> <blockquote> <p><em><strong>Le costanti devono essere sempre private o internal. Se serve esporle allora si utilizzino dei field readonly</strong>.</em></p></blockquote> <p>Augh!</p> <p> </p><div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:e23a99d5-f626-4d0a-a547-d6a97a6dad5b" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati tags: <a href="http://technorati.com/tags/Costanti" rel="tag">Costanti</a>, <a href="http://technorati.com/tags/Readonly%20field" rel="tag">Readonly field</a></div><img src="http://blogs.ugidotnet.org/Crad/aggbug/90956.aspx" width="1" height="1" /> Marco De Sanctis http://blogs.ugidotnet.org/Crad/archive/2008/01/31/costanti-pubbliche-ahiahiahi.aspx Thu, 31 Jan 2008 16:15:13 GMT http://blogs.ugidotnet.org/Crad/archive/2008/01/31/costanti-pubbliche-ahiahiahi.aspx#feedback 6 http://blogs.ugidotnet.org/Crad/comments/commentRss/90956.aspx [ADO.NET Entity Framework #0] Per iniziare http://blogs.ugidotnet.org/Crad/archive/2008/01/22/ado.net-entity-framework-0-per-iniziare.aspx <p>Ho da poco iniziato a studiare ADO.NET Entity Framework e vorrei pubblicare impressioni, tip, ecc.ecc. man mano che imparo qualcosa.</p> <p>Il primo passo per iniziare a lavorare con questo ORM di Microsoft è quello di fare qualche download, per cui oggi mi limiterò a fornire qualche link utile per utilizzare la beta 3 (in attesa della definitiva) su VS2008. La lista della spesa è più o meno questa, in ordine di installazione:</p> <ol> <li>ADO.NET Entity Framework Beta 3: <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=15DB9989-1621-444D-9B18-D1A04A21B519&amp;displaylang=en">qui</a></li> <li>Patch per installazione su VS2008 RTM: <a href="http://go.microsoft.com/fwlink?LinkID=104985">qui</a></li> <li>ADO.NET E.F. Tools (CTP di dicembre 2007): <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=D8AE4404-8E05-41FC-94C8-C73D9E238F82&amp;displaylang=en">qui</a></li> <li>SQL Server 2005, c'è la Express Edition scaricabile <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=220549b5-0b07-4448-8848-dcc397514b41&amp;displaylang=en">qui</a></li></ol> <p>That's all...</p> <p>Per iniziare a smanettare, consiglio di dare un'occhiata a <a href="http://msdn2.microsoft.com/en-us/library/bb399182.aspx">questo (MOOOOOLTO SEMPLICE) quickstart</a> e a <a href="http://www.codeplex.com/adonetsamples">questo progetto</a> su Codeplex</p> <p> </p> <div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:901a8853-749c-4dd6-9423-2041d822d484" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati tags: <a href="http://technorati.com/tags/Entity%20Framework" rel="tag">Entity Framework</a></div><img src="http://blogs.ugidotnet.org/Crad/aggbug/90805.aspx" width="1" height="1" /> Marco De Sanctis http://blogs.ugidotnet.org/Crad/archive/2008/01/22/ado.net-entity-framework-0-per-iniziare.aspx Tue, 22 Jan 2008 10:58:34 GMT http://blogs.ugidotnet.org/Crad/archive/2008/01/22/ado.net-entity-framework-0-per-iniziare.aspx#feedback 5 http://blogs.ugidotnet.org/Crad/comments/commentRss/90805.aspx A tool to manage your blog categories and Technorati Tags http://blogs.ugidotnet.org/Crad/archive/2007/09/29/a-tool-to-manage-your-blog-categories-and-technorati-tags.aspx <p>When I first decided to have a blog, I didn't have a clear idea of what I was going to talk about. It was supposed to be focused on .Net and programming topics, indeed, but figuring out a list of categories having only this in mind was extremely hard. I think that a lot of bloggers had (and keep having) the same experience and, sudden or later, almost everyone comes to the need to re-arrange post categories.</p> <p>Things get much more complicated when you decide to start Technorati-tagging your post: doing it post per post is pretty easy, just a matter of adding a couple of links. Some WLW plugins can be helpful to mantain a certain coherence on the keywords you are tagging, but what about the old posts? Can you figure out how boring and time consuming tagging old posts can be? I'm sure you can. I tried to do that job, giving up just some minutes after and deciding that I did need a tool to deal with it.</p> <p>Though, I made Blog Manager (if you have a better name to suggest, please do it, I know that "Blog Manager" is simply awful <img alt="smile_teeth" src="http://spaces.live.com/rte/emoticons/smile_teeth.gif" />) which uses MetaWeblog API to interact with blog engines and let you arrange Categories and Technorati tags with all those fancy features a Windows Explorer-like UI has, like multiple selection.</p> <p>All you need to do is setting up your connection credentials</p> <p><a href="http://www.marcodesanctis.it/images/Blog/AtooltomanageyourblogcategoriesandTechno_100F7/image025.png" atomicselection="true"><img src="http://www.marcodesanctis.it/images/Blog/AtooltomanageyourblogcategoriesandTechno_100F7/image02_thumb3.png" /></a> </p> <p>fetch some posts from your blog</p> <p><a href="http://www.marcodesanctis.it/images/Blog/AtooltomanageyourblogcategoriesandTechno_100F7/image042.png" atomicselection="true"><img src="http://www.marcodesanctis.it/images/Blog/AtooltomanageyourblogcategoriesandTechno_100F7/image04_thumb.png" /></a> </p> <p>and change categories and tags using multi-selection on the listview and three-state CheckBoxLists on the left</p> <p><a href="http://www.marcodesanctis.it/images/Blog/AtooltomanageyourblogcategoriesandTechno_100F7/image0122.png" atomicselection="true"><img src="http://www.marcodesanctis.it/images/Blog/AtooltomanageyourblogcategoriesandTechno_100F7/image012_thumb.png" /></a> </p> <p>After your work is done, just press the Save button on the toolbar to update your blog.</p> <p><strong>An important reminder</strong>: Technorati Tags feature use regular expressions to extract keywords from each post body. Although both I and my friend <a href="http://codeclimber.net.nz/">Simone Chiaretta</a> did many tests and it seems to work as expected, be aware that it can potentially mess your post text. So, please, do a backup of your blog data (there's a built in backup/restore feature in Blog Manager too) before using it.</p> <p>Oh... and please always remember that...</p> <blockquote> <p><font color="#ff0000">This application is provided as is. The copyright holder cannot be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.</font></p></blockquote> <p><font color="#400040">Here you can find both <a href="http://www.marcodesanctis.it/public/BlogManagerSolution.rar">source code</a> (in VS2008 beta 2 format) and <a href="http://www.marcodesanctis.it/public/BlogManager.rar">executables</a>.</font></p> <p><font color="#400040">EDIT: This project <a href="http://code.google.com/p/blogcommander/">has been moved</a> to <a href="http://code.google.com">Google Code</a> and renamed as </font><font color="#ff0000">Blog Commander</font></p> <div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:c8727634-be3d-4794-94b3-ef4da3d03920" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati tags: <a href="http://technorati.com/tags/Blog%20Commander" rel="tag">Blog Commander</a>, <a href="http://technorati.com/tags/Tools" rel="tag">Tools</a></div><img src="http://blogs.ugidotnet.org/Crad/aggbug/88607.aspx" width="1" height="1" /> Marco De Sanctis http://blogs.ugidotnet.org/Crad/archive/2007/09/29/a-tool-to-manage-your-blog-categories-and-technorati-tags.aspx Sat, 29 Sep 2007 19:17:59 GMT http://blogs.ugidotnet.org/Crad/archive/2007/09/29/a-tool-to-manage-your-blog-categories-and-technorati-tags.aspx#feedback 15 http://blogs.ugidotnet.org/Crad/comments/commentRss/88607.aspx LINQ = Expression Trees http://blogs.ugidotnet.org/Crad/archive/2007/09/24/linq--expression-trees.aspx <p>Quando scriviamo interrogazioni con LINQ, non dobbiamo mai perdere di vista ciò che in realtà esse sono, ossia <em>alberi di funzioni e Lambda expression</em>. Per questa ragione, un qualcosa come</p> <p></p> <div class="wlWriterEditableSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:f348bd51-0863-4d3a-b4bf-2c6a572dda93" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width: 100%; background-color: #eeeeee"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #999999">1</span> <span style="color: #000000">var customers </span><span style="color: #000000">=</span><span style="color: #000000"> db.Customers </span><span style="color: #999999">2</span> <span style="color: #000000"> .Where(c </span><span style="color: #000000">=&gt;</span><span style="color: #000000"> c.CompanyName.StartsWith(</span><span style="color: #800000">"</span><span style="color: #800000">A</span><span style="color: #800000">"</span><span style="color: #000000">)) </span><span style="color: #999999">3</span> <span style="color: #000000"> .Join(db.Orders, </span><span style="color: #999999">4</span> <span style="color: #000000"> (c </span><span style="color: #000000">=&gt;</span><span style="color: #000000"> c.CustomerID), </span><span style="color: #999999">5</span> <span style="color: #000000"> (o </span><span style="color: #000000">=&gt;</span><span style="color: #000000"> o.CustomerID), </span><span style="color: #999999">6</span> <span style="color: #000000"> (c, o) </span><span style="color: #000000">=&gt;</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> { c, o }) </span><span style="color: #999999">7</span> <span style="color: #000000"> .Where(co </span><span style="color: #000000">=&gt;</span><span style="color: #000000"> co.o.ShippedDate </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">) </span><span style="color: #999999">8</span> <span style="color: #000000"> .Select(co </span><span style="color: #000000">=&gt;</span><span style="color: #000000"> co.c).Distinct();</span></div></pre></div> <p></p> <p>è, grazie a puro <em>syntactic sugar</em>, equivalente a</p> <p></p> <div class="wlWriterEditableSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:0882695a-88a4-480f-951f-b3452a941fbf" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width: 100%; background-color: #eeeeee"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #999999">1</span> <span style="color: #000000">var customersLinq </span><span style="color: #000000">=</span><span style="color: #000000"> (from c </span><span style="color: #0000ff">in</span><span style="color: #000000"> db.Customers </span><span style="color: #999999">2</span> <span style="color: #000000"> join o </span><span style="color: #0000ff">in</span><span style="color: #000000"> db.Orders </span><span style="color: #999999">3</span> <span style="color: #000000"> on c.CustomerID equals o.CustomerID </span><span style="color: #999999">4</span> <span style="color: #000000"> </span><span style="color: #0000ff">where</span><span style="color: #000000"> c.CompanyName.StartsWith(</span><span style="color: #800000">"</span><span style="color: #800000">A</span><span style="color: #800000">"</span><span style="color: #000000">) </span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000"> </span><span style="color: #999999">5</span> <span style="color: #000000"> o.ShippedDate </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000"> </span><span style="color: #999999">6</span> <span style="color: #000000"> select c).Distinct();</span></div></pre></div> <p></p> <p>Lo snippet di cui sopra infatti, non è altro che un modo leggibile per disegnare un <strong>Expression Tree</strong>. Questo concetto, che può sembrare un <em>internal</em> come un altro e quindi generare dei "chi se ne frega" allo stesso modo di un trattato sulle tradizioni popolari indocinesi, ha in realtà un peso determinante almeno per un paio di ragioni.</p> <p>Intanto<strong> l'elaborazione non viene eseguita finchè non si cicla sul resultset</strong>; e questo, nel caso di LINQ to SQL, tanto per fare un esempio, vuol dire che finché non scriviamo</p> <p></p> <div class="wlWriterEditableSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:a4efbcff-ee2e-4ab2-8439-146a2820af8f" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width: 100%; background-color: #eeeeee"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #999999">1</span> <span style="color: #0000ff">foreach</span><span style="color: #000000"> (var item </span><span style="color: #0000ff">in</span><span style="color: #000000"> customers) </span><span style="color: #999999">2</span> <span style="color: #000000">{ </span><span style="color: #999999">3</span> <span style="color: #000000"> Console.WriteLine(item.CompanyName); </span><span style="color: #999999">4</span> <span style="color: #000000">}</span></div></pre></div> <p></p> <p>non parte nessuna query verso il DataBase.</p> <p>Inoltre, e anche in virtù anche del punto precedente, <strong>le interrogazioni LINQ possono essere concatenate tra di loro</strong>:</p> <p></p> <div class="wlWriterEditableSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:e94ff30b-c49f-49fd-8b43-ed8d6a11c089" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width: 100%; background-color: #eeeeee"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #999999">1</span> <span style="color: #000000">var customersStartingWithA </span><span style="color: #000000">=</span><span style="color: #000000"> from c </span><span style="color: #0000ff">in</span><span style="color: #000000"> db.Customers </span><span style="color: #999999">2</span> <span style="color: #000000"> </span><span style="color: #0000ff">where</span><span style="color: #000000"> c.CompanyName.StartsWith(</span><span style="color: #800000">"</span><span style="color: #800000">A</span><span style="color: #800000">"</span><span style="color: #000000">) </span><span style="color: #999999">3</span> <span style="color: #000000"> select c; </span><span style="color: #999999">4</span> <span style="color: #000000"> </span><span style="color: #999999">5</span> <span style="color: #000000">var customersWithUnshippedOrders </span><span style="color: #000000">=</span><span style="color: #000000"> (from c </span><span style="color: #0000ff">in</span><span style="color: #000000"> customersStartingWithA </span><span style="color: #999999">6</span> <span style="color: #000000"> join o </span><span style="color: #0000ff">in</span><span style="color: #000000"> db.Orders </span><span style="color: #999999">7</span> <span style="color: #000000"> on c.CustomerID equals o.CustomerID </span><span style="color: #999999">8</span> <span style="color: #000000"> </span><span style="color: #0000ff">where</span><span style="color: #000000"> o.ShippedDate </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000"> </span><span style="color: #999999">9</span> <span style="color: #000000"> select c).Distinct();</span></div></pre></div> <p></p> <p>L'esempio, relativo a LINQ to SQL, genera questa query SQL:</p> <p></p> <div class="wlWriterEditableSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:d1222125-7323-4b74-88d3-66e16eadd233" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width: 100%"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000ff">SELECT</span><span style="color: #000000"> </span><span style="color: #0000ff">DISTINCT</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">t0</span><span style="color: #ff0000">]</span><span style="color: #000000">.</span><span style="color: #ff0000">[</span><span style="color: #ff0000">CustomerID</span><span style="color: #ff0000">]</span><span style="color: #000000">, .... </span><span style="color: #0000ff">FROM</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">dbo</span><span style="color: #ff0000">]</span><span style="color: #000000">.</span><span style="color: #ff0000">[</span><span style="color: #ff0000">Customers</span><span style="color: #ff0000">]</span><span style="color: #000000"> </span><span style="color: #0000ff">AS</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">t0</span><span style="color: #ff0000">]</span><span style="color: #000000"> </span><span style="color: #0000ff">INNER</span><span style="color: #000000"> </span><span style="color: #0000ff">JOIN</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">dbo</span><span style="color: #ff0000">]</span><span style="color: #000000">.</span><span style="color: #ff0000">[</span><span style="color: #ff0000">Orders</span><span style="color: #ff0000">]</span><span style="color: #000000"> </span><span style="color: #0000ff">AS</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">t1</span><span style="color: #ff0000">]</span><span style="color: #000000"> </span><span style="color: #0000ff">ON</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">t0</span><span style="color: #ff0000">]</span><span style="color: #000000">.</span><span style="color: #ff0000">[</span><span style="color: #ff0000">CustomerID</span><span style="color: #ff0000">]</span><span style="color: #000000"> </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">t1</span><span style="color: #ff0000">]</span><span style="color: #000000">.</span><span style="color: #ff0000">[</span><span style="color: #ff0000">CustomerID</span><span style="color: #ff0000">]</span><span style="color: #000000"> </span><span style="color: #0000ff">WHERE</span><span style="color: #000000"> (</span><span style="color: #ff0000">[</span><span style="color: #ff0000">t1</span><span style="color: #ff0000">]</span><span style="color: #000000">.</span><span style="color: #ff0000">[</span><span style="color: #ff0000">ShippedDate</span><span style="color: #ff0000">]</span><span style="color: #000000"> </span><span style="color: #0000ff">IS</span><span style="color: #000000"> </span><span style="color: #808080">NOT</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000">) </span><span style="color: #808080">AND</span><span style="color: #000000"> (</span><span style="color: #ff0000">[</span><span style="color: #ff0000">t0</span><span style="color: #ff0000">]</span><span style="color: #000000">.</span><span style="color: #ff0000">[</span><span style="color: #ff0000">CompanyName</span><span style="color: #ff0000">]</span><span style="color: #000000"> </span><span style="color: #808080">LIKE</span><span style="color: #000000"> </span><span style="color: #008000">@p0</span><span style="color: #000000">)</span></div></pre></div> <p></p> <p>che condensa perfettamente il concetto che siamo riusciti a scindere nelle due più semplici interrogazioni. Ah, attenzione che non sempre l'engine di LINQ to SQL è così smart, alle volte vengono fuori query innestate non da poco <img alt="smile_teeth" src="http://spaces.live.com/rte/emoticons/smile_teeth.gif" /></p> <p>Ovviamente quanto detto è uno dei fondamenti della stessa tecnologia LINQ, pertanto non è limitata solo a LINQ to SQL, ma a tutte le possibili incarnazioni che essa ha all'interno di .Net 3.5.</p> <div class="wlWriterEditableSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:479dfa14-ea78-4b1d-84d4-37ac716e2d03" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati tags: <a href="http://technorati.com/tags/LINQ" rel="tag">LINQ</a>, <a href="http://technorati.com/tags/.Net%203.5" rel="tag">.Net 3.5</a></div><img src="http://blogs.ugidotnet.org/Crad/aggbug/88499.aspx" width="1" height="1" /> Marco De Sanctis http://blogs.ugidotnet.org/Crad/archive/2007/09/24/linq--expression-trees.aspx Mon, 24 Sep 2007 02:17:15 GMT http://blogs.ugidotnet.org/Crad/archive/2007/09/24/linq--expression-trees.aspx#feedback http://blogs.ugidotnet.org/Crad/comments/commentRss/88499.aspx Tre cosine che mi sono piaciute poco di LINQ to SQL http://blogs.ugidotnet.org/Crad/archive/2007/09/21/tre-cosine-che-mi-sono-piaciute-poco-di-linq-to.aspx <p><a href="http://blogs.ugidotnet.org/Crad/archive/2007/09/20/pensierini-della-sera-su-linq-to-sql.aspx">Ieri ne ho parlato tessendone le lodi</a>, perchè tutto sommato reputo LINQ un buon ORM, che forse però soffre di qualche peccato di gioventù. Visto che per natura sono un po' rompiballe e non mi accontento mai, infatti, vi vengo a raccontare un paio di aspetti (anzi tre) che mi sono subito saltati all'occhio e che non mi sconfinferano granché.</p> <p><strong><em>Punto 1</em></strong></p> <p>Le entity (generate da un'ottimo designer, poco da dire) <em>non sono serializzabili</em> a causa delle dipendenze da EntitySet e EntityRef. Si tratta di una brutta limitazione, che non mi permette di esporle direttamente MBV con Remoting, tanto per fare un esempio, non mi permette di memorizzarle in un Session Server, non mi permette di scriverle nel ViewState se mi voglio fare del male (o se non lo memorizzo in pagina <img alt="smile_wink" src="http://spaces.live.com/rte/emoticons/smile_wink.gif" />) and so on...</p> <p><strong><em>Punto 2</em></strong></p> <p>Le query SQL prodotte sono a volte di dubbia ottimizzazione. Se ad esempio scrivo</p> <p></p> <div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:65cd518e-26de-4786-a17f-3bd421e0e492" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width:100%;;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #999999;">1</span> <span style="color: #000000;">var orders </span><span style="color: #000000;">=</span><span style="color: #000000;"> from o </span><span style="color: #0000FF;">in</span><span style="color: #000000;"> Orders </span><span style="color: #0000FF;">where</span><span style="color: #000000;"> o.Customer.Id </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #800080;">5</span><span style="color: #000000;">;</span></div></pre></div> <p></p> <p>LINQ mi spara una bella JOIN tra la tabella degli ordini e quella dei clienti, mentre invece la condizione potrebbe essere posta utilizzando esclusivamente la prima (come fa NHibernate):</p> <p></p> <div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:8380c913-6a19-48b5-86f8-7e1cbcff8ae5" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width:100%;background-color:#EEEEEE;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF;">SELECT</span><span style="color: #000000;"> </span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">t0</span><span style="color: #FF0000;">]</span><span style="color: #000000;">.</span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">OrderID</span><span style="color: #FF0000;">]</span><span style="color: #000000;">, ... altri fields ... </span><span style="color: #0000FF;">FROM</span><span style="color: #000000;"> </span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">dbo</span><span style="color: #FF0000;">]</span><span style="color: #000000;">.</span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">Orders</span><span style="color: #FF0000;">]</span><span style="color: #000000;"> </span><span style="color: #0000FF;">AS</span><span style="color: #000000;"> </span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">t0</span><span style="color: #FF0000;">]</span><span style="color: #000000;"> </span><span style="color: #FF00FF;">LEFT</span><span style="color: #000000;"> </span><span style="color: #0000FF;">OUTER</span><span style="color: #000000;"> </span><span style="color: #0000FF;">JOIN</span><span style="color: #000000;"> </span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">dbo</span><span style="color: #FF0000;">]</span><span style="color: #000000;">.</span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">Customers</span><span style="color: #FF0000;">]</span><span style="color: #000000;"> </span><span style="color: #0000FF;">AS</span><span style="color: #000000;"> </span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">t1</span><span style="color: #FF0000;">]</span><span style="color: #000000;"> </span><span style="color: #0000FF;">ON</span><span style="color: #000000;"> </span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">t1</span><span style="color: #FF0000;">]</span><span style="color: #000000;">.</span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">CustomerID</span><span style="color: #FF0000;">]</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">t0</span><span style="color: #FF0000;">]</span><span style="color: #000000;">.</span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">CustomerID</span><span style="color: #FF0000;">]</span><span style="color: #000000;"> </span><span style="color: #0000FF;">WHERE</span><span style="color: #000000;"> </span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">t1</span><span style="color: #FF0000;">]</span><span style="color: #000000;">.</span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">CustomerID</span><span style="color: #FF0000;">]</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #008000;">@p0</span></div></pre></div> <p></p> <p>Per ovviare a questo problema, l'unico modo è esporre una proprietà CustomerID anche nella classe Order, come d'altronde fa per default il designer. "Stilisticamente" non è il massimo, ma quantomeno, se generiamo il codice da designer di Visual Studio, il setter della proprietà CustomerID solleva un'eccezione se proviamo ad impostarne un valore diverso da quello di Order.Customer.ID.</p> <p><strong><em>Punto 3</em></strong></p> <p>Piccola premessa: in LINQ to SQL ogni associazione è lazy by design (ed è una best practice); ma attenzione a chiamare la Dispose di un oggetto DataContext se gli oggetti recuperati con esso non sono stati completamente inizializzati. Consideriamo ad esempio questo metodo:</p> <p></p> <div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:4dc72541-7e36-4373-85ee-997236bd47cf" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width:100%;;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #999999;"> 1</span> <span style="color: #0000FF;">public</span><span style="color: #000000;"> Customer GetCustomerById(</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> id) </span><span style="color: #999999;"> 2</span> <span style="color: #000000;">{ </span><span style="color: #999999;"> 3</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">using</span><span style="color: #000000;"> (MyDomainDataContext db </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> MyDomainDataContext()) </span><span style="color: #999999;"> 4</span> <span style="color: #000000;"> { </span><span style="color: #999999;"> 5</span> <span style="color: #000000;"> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Recupero il customer dato il suo Id, ma attenzione: </span><span style="color: #999999;"> 6</span> <span style="color: #008000;"> </span><span style="color: #008000;">//</span><span style="color: #008000;"> la collection customer.Orders è lazy loaded e quindi </span><span style="color: #999999;"> 7</span> <span style="color: #008000;"> </span><span style="color: #008000;">//</span><span style="color: #008000;"> sarà inizializzata solo al primo accesso</span><span style="color: #008000;"> </span><span style="color: #999999;"> 8</span> <span style="color: #008000;"></span><span style="color: #000000;"> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> db.Customers.First(c </span><span style="color: #000000;">=&gt;</span><span style="color: #000000;"> c.Id </span><span style="color: #000000;">==</span><span style="color: #000000;"> id); </span><span style="color: #999999;"> 9</span> <span style="color: #000000;"> } </span><span style="color: #999999;">10</span> <span style="color: #000000;">}</span></div></pre></div> <p></p> <p>Ora, dato che la collection Orders, ancora non inizializzata, ha al suo interno una reference a <strong>*quello specifico*</strong> DataContext che l'ha creata; pertanto, accedere alla proprietà Orders al di fuori di questo metodo causerà una <em>ObjectDisposedException</em>. Fin qui me l'aspetto e lo trovo anche giusto. Attenzione però che, anche agganciando quel customer ad un altro DataContext tale reference non viene aggiornata e quindi si otterrà comunque un'eccezione.</p> <div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:29f8ac9c-f5ef-40a5-925a-b79144a45aa6" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati tags: <a href="http://technorati.com/tags/LINQ" rel="tag">LINQ</a>, <a href="http://technorati.com/tags/.Net%203.5" rel="tag">.Net 3.5</a></div><img src="http://blogs.ugidotnet.org/Crad/aggbug/88458.aspx" width="1" height="1" /> Marco De Sanctis http://blogs.ugidotnet.org/Crad/archive/2007/09/21/tre-cosine-che-mi-sono-piaciute-poco-di-linq-to.aspx Fri, 21 Sep 2007 02:32:30 GMT http://blogs.ugidotnet.org/Crad/archive/2007/09/21/tre-cosine-che-mi-sono-piaciute-poco-di-linq-to.aspx#feedback http://blogs.ugidotnet.org/Crad/comments/commentRss/88458.aspx Pensierini della sera su LINQ to SQL http://blogs.ugidotnet.org/Crad/archive/2007/09/20/pensierini-della-sera-su-linq-to-sql.aspx <p></p> <p>In questi giorni sto spulciando un pochino questo ORM e fino ad ora le mie impressioni sono senz'altro positive; <a href="http://msdn2.microsoft.com/library/bb425822.aspx">LINQ to SQL</a>, a mio modo di vedere, è un prodotto che ha dalla sua un'estrema produttività, almeno per un paio di ragioni:</p> <ol> <li>Intanto l'ottima integrazione con il designer di Visual Studio, che si interfaccia con la base dati e ci consente di modellare il dominio applicativo veramente in brevissimo tempo: la comodità del designer del DataSet applicata ad un Domain Model + ORM, praticamente il mio sogno <img alt="smile_teeth" src="http://spaces.live.com/rte/emoticons/smile_teeth.gif" /> </li><li>La semplicità e la naturalezza di LINQ come linguaggio di interrogazione, che ci consente di <em>comporre</em> (già, comporre, magari ne parlerò in un altro post) query complesse in maniera estremamente intuitiva e soprattutto strong typed (anche se alle volte si è costretti a smanettare con le lambda expression).</li></ol> <p>Ora.. è vero che il dominio viene "sporcato" dagli attributes, che c'è EntitySet per le collection e non una semplice interfaccia e che <a href="http://www.hibernate.org/343.html">NHibernate</a> rullezza, ma il mio pensiero in merito è più o meno "chi se ne frega" <img alt="smile_teeth" src="http://spaces.live.com/rte/emoticons/smile_teeth.gif" /></p> <p>Giuro che non avrei mai pensato di scrivere quel "chi se ne frega" di una riga fa, ma c'è una ragione: credo che LINQ to SQL sia, al giorno d'oggi, una soluzione estremamente valida per tutte quelle applicazioni - e sono tante - che difficilmente vedranno una versione 2.0. Per questa ragione un paragone con <a href="http://www.hibernate.org/343.html">NHibernate</a> è un pochino fuorviante e mal posto: il target è diverso, al massimo paragoniamolo ad <a href="http://www.castleproject.org/activerecord/index.html">Active Record</a> e comunque consideriamolo un ORM dall'approccio molto più easy e anche parecchio RAD. Questo giustifica anche il punto 1 in alto, che magari avrà fatto storcere il naso a quanti, <strong>come il sottoscritto</strong> d'altronde, sono convinti che le entity di dominio vadano modellate a prescindere dallo schema del database.</p> <p>Ovviamente non è tutto rose e fiori, ci sono aspetti che non mi hanno convinto fino in fondo, ma di questo scriverò (spero di averne il tempo) domani.</p> <div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:83c75623-df2f-4437-877f-d6c5ec7bfefd" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati tags: <a href="http://technorati.com/tags/LINQ" rel="tag">LINQ</a>, <a href="http://technorati.com/tags/NHibernate" rel="tag">NHibernate</a>, <a href="http://technorati.com/tags/.Net%203.5" rel="tag">.Net 3.5</a></div><img src="http://blogs.ugidotnet.org/Crad/aggbug/88432.aspx" width="1" height="1" /> Marco De Sanctis http://blogs.ugidotnet.org/Crad/archive/2007/09/20/pensierini-della-sera-su-linq-to-sql.aspx Thu, 20 Sep 2007 01:40:41 GMT http://blogs.ugidotnet.org/Crad/archive/2007/09/20/pensierini-della-sera-su-linq-to-sql.aspx#feedback 1 http://blogs.ugidotnet.org/Crad/comments/commentRss/88432.aspx Un semplice tool per gestire le categorie sul blog http://blogs.ugidotnet.org/Crad/archive/2007/09/13/un-semplice-tool-per-gestire-le-categorie-sul-blog.aspx <p><a href="http://blogs.ugidotnet.org/Crad/archive/2007/09/11/xml-rpc-e-.net.aspx">Ne avevo parlato un paio di giorni fa</a>. Vorrei riorganizzare le categorie sul mio blog, eliminando quelle poco usate ed assegnando i relativi post ad altre (nuove e non), ma sono sempre stato frenato dal fatto che farlo il manager web può essere veramente noioso ed estenuante.</p> <p>Domenica scorsa allora, con un po' di tempo libero, mi sono messo a realizzare una semplice applicazione Windows Forms che, facendo uso delle MetaWeblog API, semplificasse di molto il lavoro; fatto sta che ho prodotto questa cosina qui:</p> <p>1) Dopo aver configurato le impostazioni di accesso dal menu opzioni...</p> <p><a href="http://www.marcodesanctis.it/images/Blog/Unsemplicetoolpergestirelecategoriesulbl_A56/image03.png" atomicselection="true"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="132" src="http://www.marcodesanctis.it/images/Blog/Unsemplicetoolpergestirelecategoriesulbl_A56/image02.png" width="240" border="0" /></a> </p> <p>2) è possibile visualizzare le categorie e recuperare un certo numero di post dal proprio blog</p> <p><a href="http://www.marcodesanctis.it/images/Blog/Unsemplicetoolpergestirelecategoriesulbl_A56/image05.png" atomicselection="true"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="162" src="http://www.marcodesanctis.it/images/Blog/Unsemplicetoolpergestirelecategoriesulbl_A56/image04.png" width="240" border="0" /></a> </p> <p>A questo punto, grazie anche alle possibilità di filtro e di selezione multipla, è facile e veloce modificare le associazioni Post-Categorie nella CheckBoxList a sinistra.</p> <p>Una nota importantissima:</p> <blockquote> <p><em><font color="#ff0000">Questo software è rilasciato gratuitamente "AS IS". L'autore (cioé il sottoscritto) non è in alcun modo tenuto a fornire assistenza né tantomeno potrà essere ritenuto responsabile per eventuali problemi inerenti il suo utilizzo. In altre parole, se vi si sminchia totalmente il blog, il sistema operativo, se un hacker accede al vostro conto in banca, ecc.ecc., non bussate alla mia porta!</font></em></p></blockquote> <p><font color="#400040">Ciò detto, <a href="http://www.marcodesanctis.it/public/BlogManagerSolution.rar">a questo link</a> trovate i sorgenti.</font></p> <p><font color="#400040">Ah.. per inciso, le mie categorie sono ancora lì dov'erano <img alt="smile_teeth" src="http://spaces.live.com/rte/emoticons/smile_teeth.gif" /></font></p> <div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:5cb9ec3e-737c-4085-8325-c642737fb585" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati tags: <a href="http://technorati.com/tags/Tools" rel="tag">Tools</a>, <a href="http://technorati.com/tags/Blog%20Commander" rel="tag">Blog Commander</a></div><img src="http://blogs.ugidotnet.org/Crad/aggbug/88294.aspx" width="1" height="1" /> Marco De Sanctis http://blogs.ugidotnet.org/Crad/archive/2007/09/13/un-semplice-tool-per-gestire-le-categorie-sul-blog.aspx Thu, 13 Sep 2007 01:48:27 GMT http://blogs.ugidotnet.org/Crad/archive/2007/09/13/un-semplice-tool-per-gestire-le-categorie-sul-blog.aspx#feedback 4 http://blogs.ugidotnet.org/Crad/comments/commentRss/88294.aspx Linq e Reflector http://blogs.ugidotnet.org/Crad/archive/2007/09/09/linq-e-reflector.aspx <p>Il più grande punto di forza di Microsoft LINQ è senza dubbio quel <em>syntactic sugar</em> che ci permette di scrivere query simil-SQL, strong typed e direttamente all'interno del codice C# (o VB.NET che sia).</p> <p>Supponiamo di voler recuperare, dagli assembly in memoria, l'elenco delle classi che iniziano per una data lettera. In C# 3.0 posso scrivere qualcosa tipo</p> <div class="CodeFormatContainer"> <style><!-- .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> <div class="csharpcode"><pre class="alt"><span class="lnum"> 1: </span>var types =</pre><pre><span class="lnum"> 2: </span> from assembly <span class="kwrd">in</span> AppDomain.CurrentDomain.GetAssemblies()</pre><pre class="alt"><span class="lnum"> 3: </span> from type <span class="kwrd">in</span> assembly.GetTypes()</pre><pre><span class="lnum"> 4: </span> <span class="kwrd">where</span> type.Name.StartsWith(<span class="str">"C"</span>) &amp;&amp; type.IsClass</pre><pre class="alt"><span class="lnum"> 5: </span> select <span class="kwrd">new</span> { Namespace = type.Namespace, Name = type.Name };</pre><pre><span class="lnum"> 6: </span> </pre><pre class="alt"><span class="lnum"> 7: </span><span class="kwrd">foreach</span> (var type <span class="kwrd">in</span> types)</pre><pre><span class="lnum"> 8: </span>{</pre><pre class="alt"><span class="lnum"> 9: </span> Console.WriteLine(<span class="str">"{0} \t {1}"</span>, type.Namespace, type.Name);</pre><pre><span class="lnum"> 10: </span>}</pre></div></div> <p>In realtà, ciò che avviene <em>under the hood</em>, è che il compilatore si fa carico di trasformare codice di questo tipo in qualcosa che sia traducibile in IL, facendo uso intensivo di <em>extension methods, anonymous types</em>, ecc.</p> <p>Il risultato di tutto ciò è che, disassemblando quanto compilato con Reflector, ciò che ci si trova davanti è qualcosa del tipo...</p> <p><a href="http://www.marcodesanctis.it/images/Blog/LinqeReflector_B8EF/image.png" atomicselection="true"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="217" alt="Reflector disassemble" src="http://www.marcodesanctis.it/images/Blog/LinqeReflector_B8EF/image_thumb.png" width="511" border="0" /></a></p> <p>Morale: da domani, attenzione ad aver sotto mano anche i sorgenti veri e propri, perché Reflector da solo non basterà più.</p> <div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:d8ca6568-2954-4e56-9847-bbdedf42a25b" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati tags: <a href="http://technorati.com/tags/.Net%203.5" rel="tag">.Net 3.5</a>, <a href="http://technorati.com/tags/LINQ" rel="tag">LINQ</a></div><img src="http://blogs.ugidotnet.org/Crad/aggbug/88200.aspx" width="1" height="1" /> Marco De Sanctis http://blogs.ugidotnet.org/Crad/archive/2007/09/09/linq-e-reflector.aspx Sun, 09 Sep 2007 14:20:53 GMT http://blogs.ugidotnet.org/Crad/archive/2007/09/09/linq-e-reflector.aspx#feedback http://blogs.ugidotnet.org/Crad/comments/commentRss/88200.aspx