<?xml version="1.0" encoding="iso-8859-15"?><feed version="0.3" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns="http://purl.org/atom/ns#" xml:lang="it-it"><title>AZ - Il blog di Andrea Zani</title><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/" /><tagline type="text/html">AZ - Il blog di Andrea Zani</tagline><id>http://blogs.aspitalia.com/az/</id><generator url="http://feed.aspitalia.com/" version="ASPItalia.com">feed.ASPItalia.com 'Weyoh' 4.8.908</generator><author><name>AZ - Il blog di Andrea Zani</name><url>http://blogs.aspitalia.com/az/</url></author><modified>2008-09-06T08:52:04+00:00</modified><entry><title>Entity Framework. Una tabella due Entity senza discriminazioni</title><id>http://blogs.aspitalia.com/az/post2383/Entity-Framework.-Tabella-Entity-Discriminazioni.aspx</id><created>2008-09-06T08:52:04+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2383' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;In un &lt;a href=&quot;http://blogs.aspitalia.com/az/post2377/entity-framework-ereditarieta-single-table-inheritance.aspx&quot;&gt;blog precedente&lt;/a&gt; avevo parlato del &lt;em&gt;Single Table Inheritance&lt;/em&gt;. Grazie ad un campo apposito &#232; possibile decidere a quale &lt;em&gt;entity&lt;/em&gt; far&#224; parte il record di quella nostra tabella.&lt;/p&gt; &lt;p&gt;Il problema che sto cercando di risolvere in questi giorni si basa sul quesito:&lt;/p&gt; &lt;p&gt;&lt;em&gt;E' possibile dividere una tabella in due entity &lt;strong&gt;senza&lt;/strong&gt; questo campo?&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Ma prima che subentri la confusione, il mio obbiettivo non &#232; quello di creare due &lt;em&gt;entity&lt;/em&gt; parallele come nel caso di quel blog (&lt;em&gt;TextContents&lt;/em&gt; e &lt;em&gt;LinkContents&lt;/em&gt;), ma una &lt;em&gt;entity&lt;/em&gt; di base da cui deriva un'altra &lt;em&gt;entity&lt;/em&gt;. Per esempio, da questa tabella:&lt;/p&gt; &lt;table cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;400&quot; border=&quot;1&quot; unselectable=&quot;on&quot;&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;strong&gt;&lt;em&gt;Nome campo&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;strong&gt;&lt;em&gt;Tipo&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Id&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;int&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Title&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;nvarchar(50)&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;LongDescriptions&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;ntext&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Vorrei ottenere una struttura come questa (poi spiegher&#242; il perch&#233;):&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;300&quot; alt=&quot;nuove entity&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/ent.unatabelladueentitysenzadiscriminazi_8fd2/image_1.png&quot; width=&quot;180&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;Il problema che mi ero posto &#232; molto semplice: in caso volessi visualizzare tutti i record della tabella in un menu di scelta, la richiesta dei dati presenti in un'unica &lt;em&gt;entity&lt;/em&gt; avrebbe richiesto tutti i campi anche quelli &lt;em&gt;ntext&lt;/em&gt; (che potrebbero contenere, per assurdo, mega di documenti di testo), come si pu&#242; evitare questo?&lt;/p&gt; &lt;p&gt;Ah, dimenticavo, visto che questi dati devono attraversare dei layer dell'applicativo, non voglio usare gli anonynous type, altrimenti sarebbe troppo facile scrivere:&lt;/p&gt; &lt;p&gt;&lt;em&gt;var coll=from d in Context.Documents&lt;br /&gt; select new { Id=d.Id, Title=d.Title };&lt;br /&gt;return coll;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Anche se questa soluzione porta l'&lt;em&gt;Entity Framework&lt;/em&gt; a inviare la giusta query al database:&lt;/p&gt; &lt;p&gt;&lt;em&gt;SELECT &lt;br /&gt;1 AS [C1], &lt;br /&gt;[Extent1].[Id] AS [Id], &lt;br /&gt;[Extent1].[Title] AS [Title]&lt;br /&gt;FROM [dbo].[Descriptions] AS [Extent1]&lt;/em&gt; &lt;p&gt;Una soluzione che mi hanno suggerito &#232; creare una classe che ospiti solo quei dati: &lt;p&gt;&lt;em&gt;public class Elenco&lt;br /&gt;{&lt;br /&gt; public int Id { get; set; }&lt;br /&gt; public string Title { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var coll = from c in context.Descriptions&lt;br /&gt; select new Elenco { Id = c.Id, Title = c.Title };&lt;br /&gt;foreach (var item in coll)&lt;br /&gt;{&lt;br /&gt; Response.Write(string.Format(&lt;br /&gt; &quot;{0} {1} &amp;lt;br /&amp;gt;&quot;,&lt;br /&gt; item.Id,&lt;br /&gt; item.Title&lt;br /&gt; ));&lt;br /&gt;} &lt;/em&gt; &lt;p&gt;Pu&#242; andare. Si potrebbe trovare un'altra soluzione con l'uso delle viste. Creata questa vista: &lt;p&gt;&lt;em&gt;select Id,Title from Descriptions&lt;/em&gt; &lt;p&gt;Si possono creare due &lt;em&gt;entity&lt;/em&gt; distinte all'interno dell'editor di &lt;em&gt;Visual Studio 2008&lt;/em&gt;: &lt;p&gt;&lt;img height=&quot;322&quot; alt=&quot;due entity con tabella e vista&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/ent.unatabelladueentitysenzadiscriminazi_8fd2/image_3.png&quot; width=&quot;190&quot; border=&quot;0&quot; /&gt; &lt;p&gt;Lo schifo &#232; che sono due &lt;em&gt;entity&lt;/em&gt; distinte, ma risolvono in parte il problema. Segnalo che, importata questa vista nell'editor, i campi vengono visti entrambi come &lt;em&gt;key&lt;/em&gt;. Non &#232; sufficiente modificare le propriet&#224; nell'editor, &#232; necessario aprire il file .edmx con un editor xml e cancellare la doppia key: &lt;p&gt;&lt;em&gt;&amp;lt;EntityType Name=&quot;DescriptionsTitles&quot;&amp;gt;&lt;br /&gt; &amp;lt;Key&amp;gt;&lt;br /&gt; &amp;lt;PropertyRef Name=&quot;Id&quot; /&amp;gt;&lt;br /&gt; &amp;lt;PropertyRef Name=&quot;Title&quot; /&amp;gt;&lt;strong&gt; &amp;lt;-- Da cancellare&lt;br /&gt;&lt;/strong&gt; &amp;lt;/Key&amp;gt;&lt;br /&gt; &amp;lt;Property Name=&quot;Id&quot; Type=&quot;int&quot; Nullable=&quot;false&quot; StoreGeneratedPattern=&quot;Identity&quot; /&amp;gt;&lt;br /&gt; &amp;lt;Property Name=&quot;Title&quot; Type=&quot;nvarchar&quot; Nullable=&quot;false&quot; MaxLength=&quot;50&quot; /&amp;gt;&lt;br /&gt;&amp;lt;/EntityType&amp;gt;&lt;br /&gt;&amp;lt;EntityType Name=&quot;DescriptionsTitles&quot;&amp;gt;&lt;br /&gt; &amp;lt;Key&amp;gt;&lt;br /&gt; &amp;lt;PropertyRef Name=&quot;Id&quot; /&amp;gt;&lt;br /&gt; &amp;lt;PropertyRef Name=&quot;Title&quot; /&amp;gt; &lt;strong&gt;&amp;lt;-- Da cancellare&lt;br /&gt;&lt;/strong&gt; &amp;lt;/Key&amp;gt;&lt;br /&gt; &amp;lt;Property Name=&quot;Id&quot; Type=&quot;Int32&quot; Nullable=&quot;false&quot; /&amp;gt;&lt;br /&gt; &amp;lt;Property Name=&quot;Title&quot; Type=&quot;String&quot; Nullable=&quot;false&quot; /&amp;gt;&lt;br /&gt;&amp;lt;/EntityType&amp;gt;&lt;/em&gt; &lt;p&gt;Poco sopra nell'xml &#232; possibile vedere com'&#232; importata la vista:&lt;/p&gt; &lt;p&gt;&lt;em&gt; &amp;lt;EntitySet Name=&quot;DescriptionsTitles&quot; EntityType=&quot;TestEntitiesModel.Store.DescriptionsTitles&quot; store:Type=&quot;Views&quot; store:Schema=&quot;dbo&quot; store:Name=&quot;DescriptionsTitles&quot;&amp;gt;&lt;br /&gt; &amp;lt;DefiningQuery&amp;gt;SELECT &lt;br /&gt;[DescriptionsTitles].[Id] AS [Id], &lt;br /&gt;[DescriptionsTitles].[Title] AS [Title]&lt;br /&gt;FROM [dbo].[DescriptionsTitles] AS [DescriptionsTitles]&lt;br /&gt; &amp;lt;/DefiningQuery&amp;gt;&lt;br /&gt; &amp;lt;/EntitySet&amp;gt;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Questo comporta, alla richiesta dei dati, l'esecuzione di questa query:&lt;/p&gt; &lt;p&gt;&lt;em&gt;SELECT &lt;br /&gt;[Extent1].[Id] AS [Id], &lt;br /&gt;[Extent1].[Title] AS [Title]&lt;br /&gt;FROM (SELECT &lt;br /&gt; [DescriptionsTitles].[Id] AS [Id], &lt;br /&gt; [DescriptionsTitles].[Title] AS [Title]&lt;br /&gt; FROM [dbo].[DescriptionsTitles] AS [DescriptionsTitles]) AS [Extent1]&lt;/em&gt; &lt;p&gt;Alla fine c'&#232; la soluzione compatibile con l'&lt;em&gt;Entity Framework&lt;/em&gt; e la mia necessit&#224;. Ma si deve mettere mano alla struttura del database. Si deve dividere quella tabella in due, spostando il campo &lt;em&gt;LongDescriptions&lt;/em&gt; nella seconda naturalmente collegando il tutto. L'EF non far&#224; una piega e vedr&#224; il tutto in modo corretto e otterrei ci&#242; che voglio. &lt;p&gt; &lt;p&gt;&lt;em&gt;Posso avere tutto ci&#242; che voglio? No, non &#232; possibile.&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2383/Entity-Framework.-Tabella-Entity-Discriminazioni.aspx"/><issued>2008-09-06T10:52:04+00:00</issued><modified>2008-09-06T10:52:04+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2383/Entity-Framework.-Tabella-Entity-Discriminazioni.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2383.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2383</trackback:ping></entry><entry><title>Intellisense in Sql Server 2008</title><id>http://blogs.aspitalia.com/az/post2382/Intellisense-Sql-Server-2008.aspx</id><created>2008-09-04T17:48:52+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2382' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;C'&amp;#232; una tabella:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;226&quot; alt=&quot;lista tabelle in sql server 2008&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/intellisenseinsqlserver2008_115fa/image_6.png&quot; width=&quot;226&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;L'intellisense c'&amp;#232;?&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;260&quot; alt=&quot;intellisense in sql server 2008&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/intellisenseinsqlserver2008_115fa/image_5.png&quot; width=&quot;514&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;Che bello. Cancello la tabella. Rifaccio una query e cosa mi compare?&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;305&quot; alt=&quot;intellisense con la tabella cancellata&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/intellisenseinsqlserver2008_115fa/image_9.png&quot; width=&quot;524&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p&gt;Ma se l'ho cancellata!!!&lt;/p&gt; &lt;p&gt;Il bello avviene anche con tabelle nuove che non vengono viste dall'intellisense del Managment Studio di Sql Server 2008. Lo si deve riavviare per aggiornare il tutto. &lt;/p&gt; &lt;p&gt;O mi &amp;#232; sfuggito qualcosa? La delusione per&amp;#242; c'&amp;#232;. Bel &lt;strong&gt;&lt;em&gt;bug&lt;/em&gt;&lt;/strong&gt;!!!&lt;/p&gt; &lt;p&gt;&lt;em&gt;Questo problema me l'ha fatto notare un collega, da quando c'&amp;#232; EF, Sql server non lo guardo pi&amp;#249; :-)&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/Database/&quot; rel=&quot;tag&quot;&gt;Database&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/SQL_Server/&quot; rel=&quot;tag&quot;&gt;SQL Server&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2382/Intellisense-Sql-Server-2008.aspx"/><issued>2008-09-04T19:48:52+00:00</issued><modified>2008-09-04T19:48:52+00:00</modified><slash:comments>15</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2382/Intellisense-Sql-Server-2008.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2382.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2382</trackback:ping></entry><entry><title>Entity Framework e pi&amp;#249; tabelle in una entity</title><id>http://blogs.aspitalia.com/az/post2379/Entity-Framework-Tabelle-Entity.aspx</id><created>2008-09-03T07:09:34+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2379' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Breve e coinciso. Due tabelle in una sola &lt;em&gt;entity&lt;/em&gt;. L'&lt;em&gt;Entity Framework&lt;/em&gt; lo permette con pochi passaggi e &lt;strong&gt;non&lt;/strong&gt; in automatico.&lt;/p&gt; &lt;p&gt;Mi servono due tabelle. Eccole:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Tutorials&lt;/strong&gt;&lt;/p&gt; &lt;table cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;400&quot; border=&quot;1&quot;&gt;&lt;tbody&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;strong&gt;Nome campo&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;strong&gt;Tipo e altro&lt;/strong&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Id&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Int, key, Auto increment&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Name&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;nvarchar&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Description&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Text&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&lt;strong&gt;Tutorials2&lt;/strong&gt;&lt;/p&gt; &lt;table cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;400&quot; border=&quot;1&quot;&gt;&lt;tbody&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;strong&gt;Nome campo&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;strong&gt;Tipo e altro&lt;/strong&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Id&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Int, key&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Name&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;nvarchar&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Description&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;Text&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Ora importiamo le due tabelle nel &lt;em&gt;designer&lt;/em&gt; di Visual Studio 2008. Creer&amp;#224; due &lt;em&gt;entity&lt;/em&gt; distinte. Non ci servono a nulla. Vanno cancellate. Quindi dalla &lt;em&gt;toolbar&lt;/em&gt;, inserire una nuovo oggetto &lt;em&gt;Entity&lt;/em&gt; e si mappano all'interno le due tabelle e tutti i campi, naturalmente inserendo nell'editor tante propriet&amp;#224; quante ne servono. Il risultato finale deve essere simile a questo:&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;img height=&quot;568&quot; alt=&quot;mapping entity framework&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/entityframeworkepitabelleinunaentity_80c1/immagine%204_3.gif&quot; width=&quot;510&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;Tutto fatto. Ora possiamo farne quello che vogliamo:&lt;/p&gt; &lt;p&gt;&lt;em&gt;using (pubsModel.pubsEntities context = new pubsModel.pubsEntities()) &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; pubsModel.Tutorials obj = new pubsModel.Tutorials(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; obj.Name1 = &amp;quot;A1&amp;quot;; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; obj.Name2 = &amp;quot;A2&amp;quot;; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; obj.Description1 = &amp;quot;D1&amp;quot;; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; obj.Description2 = &amp;quot;D2&amp;quot;; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.AddToTutorialsSet(obj); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.SaveChanges(); &lt;br /&gt;} &lt;/em&gt;&lt;/p&gt; &lt;p&gt;Un ringraziamento a &lt;a title=&quot;link esterno&quot; href=&quot;http://blogs.dotnethell.it/david/&quot;&gt;David&lt;/a&gt; che mi ha dato un ottimo suggerimento a riguardo. Ora ho solo un unico dubbio e poi con l'&lt;em&gt;EF&lt;/em&gt; spacco tutto: dividere una tabella in due o pi&amp;#249; &lt;em&gt;entity&lt;/em&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2379/Entity-Framework-Tabelle-Entity.aspx"/><issued>2008-09-03T09:09:34+00:00</issued><modified>2008-09-03T09:09:34+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2379/Entity-Framework-Tabelle-Entity.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2379.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2379</trackback:ping></entry><entry><title>L'Entity Framework e le custom class coinvolte nei where...</title><id>http://blogs.aspitalia.com/az/post2378/LEntity-Framework-Custom-Class-Coinvolte-Where.aspx</id><created>2008-08-31T01:04:02+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2378' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Riprendo il solito esempio di &lt;em&gt;entity&lt;/em&gt;:&lt;/p&gt; &lt;p&gt;&lt;img alt=&quot;entity in visual studio 2008&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/entityframew.unminimodicachefacevaschifo_10861/image_6.png&quot; /&gt; &lt;/p&gt; &lt;p&gt;Ipotizzando di voler recuperare tutti gli &lt;em&gt;Articles&lt;/em&gt; con un determinato colore si potrebbe essere spinti a scrivere:&lt;/p&gt; &lt;p&gt;&lt;em&gt;var c=Context.Colors.Where(cc=&amp;gt;cc.Id==1).First();&lt;br /&gt;var coll=from ar in Context.Articles.Include(&quot;Colors&quot;)&lt;br /&gt; where ar.Colors=c&lt;br /&gt; select ar;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Semplicemente, avendo una &lt;em&gt;entity&lt;/em&gt; voglio vedere tutte le &lt;em&gt;entity&lt;/em&gt; che hanno come &lt;em&gt;property&lt;/em&gt; questo oggetto. Eseguita, per&#242;, si ottienere questo errore:&lt;/p&gt; &lt;p&gt;&lt;em&gt;Unable to create a constant value of type 'Closure type'. Only primitive types (for instance Int32, String and Guid) are supported in this context.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Questo perch&#233; l'EF non permette il confronto tra &lt;em&gt;oggetti complessi&lt;/em&gt;. La soluzione &#232; banale, anzi, in qualche caso pi&#249; semplice (nel caso di &lt;em&gt;web control&lt;/em&gt; che ritornano un valore numerico per identificare una scelta di un utente, per sempio da un &lt;em&gt;dropdownlist&lt;/em&gt;):&lt;/p&gt; &lt;p&gt;&lt;em&gt;int c=int.Parse(ddl_colors.SelectedValue); // &amp;lt;- prendo il colore selezionato&lt;br /&gt;var coll=from ar in Context.Articles.Include(&quot;Colors&quot;)&lt;br /&gt; where ar.Colors.Id=c&lt;br /&gt; select ar;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Oppure:&lt;/p&gt; &lt;p&gt;&lt;em&gt;var c=Context.Colors.Where(cc=&amp;gt;cc.Id==1).First();&lt;br /&gt;var coll=from ar in Context.Articles.Include(&quot;Colors&quot;)&lt;br /&gt; where ar.Colors.Id=c.Id&lt;br /&gt; select ar;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Soluzione semplice, ma &#232; sempre bene saperla.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2378/LEntity-Framework-Custom-Class-Coinvolte-Where.aspx"/><issued>2008-08-31T03:04:02+00:00</issued><modified>2008-08-31T03:04:02+00:00</modified><slash:comments>2</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2378/LEntity-Framework-Custom-Class-Coinvolte-Where.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2378.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2378</trackback:ping></entry><entry><title>Entity Framework e l'ereditariet&amp;#224; (Single Table Inheritance)</title><id>http://blogs.aspitalia.com/az/post2377/Entity-Framework-Ereditarieta-Single-Table-Inheritance.aspx</id><created>2008-08-30T13:07:56+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2377' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Visto che in questi gioni sto usando parecchio con l'&lt;em&gt;Entity Framework&lt;/em&gt; questa &lt;em&gt;Table Per Hierarchy&lt;/em&gt; (Emanuele mi corregger&#224; se, come al solito, sbaglio la nomenclatura), ecco due appunti su come si realizza con l'editor che mette a disposizione Visual Studio 2008.&lt;/p&gt; &lt;p&gt;L'inizio &#232; questa semplice tabella dal nome &lt;em&gt;BaseContents&lt;/em&gt;:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;180&quot; alt=&quot;struttura tabella&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/entityframeworkelereditarietsingletablei_c776/image_1.png&quot; width=&quot;340&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;Da questa singola tabella &#232; possibile estrarre due &lt;em&gt;entity&lt;/em&gt; distinte. Nel mio caso:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;TextContents &lt;li&gt;LinkContents&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;La prima utilizzata per memorizzare il contenuto reale di un eventuale testo, la seconda per link a risorse esterne. All'interno di questa singola tabella sono contenuti tutti i campi per memorizzare queste informazioni. L'unico campo aggiuntivo, che far&#224; da &lt;em&gt;discriminante&lt;/em&gt;, come si vedr&#224; di seguito, &#232; &lt;em&gt;Type&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;Creato in Visual Studio 2008 un nuovo oggetto &lt;em&gt;ADO.Net Entity Data Model&lt;/em&gt;, e importanto all'interno di questo oggetto la tabella sopra mostrata, si avr&#224; la prima &lt;em&gt;entity&lt;/em&gt; creata in automatico dall'ambiente di sviluppo con tutti i campi interessati.&lt;/p&gt; &lt;p&gt;Ora &#232; possibile aggiunere le entity mancanti, &lt;em&gt;TextContents&lt;/em&gt; e &lt;em&gt;LinkContents&lt;/em&gt;, ereditandole direttamente da questa (&#232; sufficiente cliccare con il tasto destro all'interno dell'editor e selezionare &lt;em&gt;Add&lt;/em&gt; -&amp;gt; &lt;em&gt;Entity&lt;/em&gt;). Aggiunte le due entity ecco cosa abbiamo in VS 2008:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;346&quot; alt=&quot;entity&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/entityframeworkelereditarietsingletablei_c776/image_7.png&quot; width=&quot;342&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;Ora possiamo spostare le &lt;em&gt;property&lt;/em&gt; di nostro interesse nelle sottostanti &lt;em&gt;entity &lt;/em&gt;per ottenere questo:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;376&quot; alt=&quot;entity&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/entityframeworkelereditarietsingletablei_c776/image_9.png&quot; width=&quot;340&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;Dalla window Mapping details, mappiamo la tabella e assicurati che tutti i campi interessati siamo mappati correttamente, possiamo inserire la condizione discriminante, in modo che nell'uso di una o dell'altra entity, siano salvati i dati corretti nella tabella. Nulla di difficile, sempre da &lt;em&gt;Mapping details&lt;/em&gt;, si aggiunge nelle &lt;em&gt;condition&lt;/em&gt;:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://blogs.aspitalia.com/img/andrewz/entityframeworkelereditarietsingletablei_c776/image_10.png&quot; atomicselection=&quot;true&quot;&gt;&lt;img height=&quot;174&quot; alt=&quot;conditions&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/entityframeworkelereditarietsingletablei_c776/image_thumb_5.png&quot; width=&quot;520&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In questo caso ho inserito il valore &lt;em&gt;1&lt;/em&gt; in &lt;em&gt;Type&lt;/em&gt; per il &lt;em&gt;TextContents&lt;/em&gt;, e &lt;em&gt;2&lt;/em&gt; per il &lt;em&gt;LinkContents&lt;/em&gt;. Sembra tutto fatto, ma ecco l'amara sorpresa che ho trovato compilando il tutto:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Error 1 Error 3032: Problem in Mapping Fragment starting at line 49: Condition member 'BaseContents.Type' with a condition other than 'IsNull=False' is mapped. Either remove the condition on BaseContents.Type or remove it from the mapping.&lt;/strong&gt; &lt;p&gt;Scopro che &lt;em&gt;Type&lt;/em&gt; crea un problema. Il mio primo tentativo di cancellazione di questa property dall'&lt;em&gt;entity&lt;/em&gt; &lt;em&gt;BaseContents&lt;/em&gt; mi porta un nuovo errore: &lt;p&gt;&lt;strong&gt;Error 1 Error 3023: Problem in Mapping Fragments starting at lines 48, 54, 59: Column BaseContents.Type has no default value and is not nullable. A column value is required to store entity data.&lt;br /&gt;An Entity with Key (PK) will not round-trip when:&lt;br /&gt; (PK is in 'BaseContents' EntitySet AND Entity is type TestEntitiesModel.BaseContents)&lt;/strong&gt; &lt;p&gt;Alla fine scopro la soluzione da un &lt;a href=&quot;http://weblogs.asp.net/zeeshanhirani/archive/2008/08/16/single-table-inheritance-in-entity-framework.aspx&quot;&gt;blog&lt;/a&gt; di &lt;a href=&quot;http://weblogs.asp.net/zeeshanhirani/default.aspx&quot;&gt;Zeeshan Hirani&lt;/a&gt; (che spiega il tutto in modo molto pi&#249; dettagliato, ma visto che ho scritto fino a qua, non ho voglia di buttare il tutto) che ringrazio perch&#233; mi ha fatto trovare immediatamente la soluzione. E' sufficiente modificare la &lt;em&gt;property&lt;/em&gt; &lt;em&gt;Abstract&lt;/em&gt; dell&lt;em&gt;'Entity BaseContents&lt;/em&gt; in &lt;em&gt;true&lt;/em&gt;, per eliminare ogni errore. &lt;p&gt;Ora da codice possiamo inserire e leggere da questa tabella con due &lt;em&gt;entity&lt;/em&gt; separate: &lt;p&gt;&lt;em&gt;using (TestEntitiesModel.TestEntitiesEntities context = new TestEntitiesModel.TestEntitiesEntities())&lt;br /&gt;{&lt;br /&gt; TestEntitiesModel.TextContents c = new TestEntitiesModel.TextContents();&lt;br /&gt; c.Name = &quot;Example 1&quot;;&lt;br /&gt; c.Content = &quot;Content text bla bla bla&quot;;&lt;br /&gt; context.AddToBaseContents(c);&lt;br /&gt; TestEntitiesModel.LinkContents l = new TestEntitiesModel.LinkContents();&lt;br /&gt; l.Name = &quot;Example 2&quot;;&lt;br /&gt; l.Link = &quot;www.aspitalia.com&quot;;&lt;br /&gt; l.Impressions = 0;&lt;br /&gt; context.AddToBaseContents(l);&lt;br /&gt; context.SaveChanges();&lt;br /&gt;} &lt;/em&gt; &lt;p&gt;Visualizzando il contenuto della tabella troveremo:&lt;/p&gt; &lt;table cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;510&quot; border=&quot;1&quot; unselectable=&quot;on&quot;&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td  width=&quot;66&quot;&gt;I&lt;strong&gt;d&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;&lt;strong&gt;Impressions&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;&lt;strong&gt;Content&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;66&quot;&gt;1&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;Example1&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;&lt;em&gt;null&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;&lt;em&gt;null&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;Content text bla bla bla&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;66&quot;&gt;2&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;Example2&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;www.aspitalia.com&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;1&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;&lt;em&gt;null&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;66&quot;&gt;2&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Per leggere:&lt;/p&gt; &lt;p&gt;&lt;em&gt;using (TestEntitiesModel.TestEntitiesEntities context = new TestEntitiesModel.TestEntitiesEntities())&lt;br /&gt;{&lt;br /&gt; var coll = from c in context.BaseContents.OfType&amp;lt;TestEntitiesModel.TextContents&amp;gt;()&lt;br /&gt; orderby c.Content ascending&lt;br /&gt; select c;&lt;br /&gt; foreach (var item in coll)&lt;br /&gt; {&lt;br /&gt; Response.Write(string.Format(&quot;{0} {1} {2}&amp;lt;br /&amp;gt;&quot;,&lt;br /&gt; item.Id,item.Name,item.Content));&lt;br /&gt; }&lt;br /&gt;} &lt;/em&gt;&lt;/p&gt; &lt;p&gt;Questa volta per specificare l'&lt;em&gt;entity&lt;/em&gt; da leggere, dobbiamo utilizzare l'&lt;em&gt;OfType&lt;/em&gt; come da esempio. Se volessimo richiedere l'&lt;em&gt;entity&lt;/em&gt; &lt;em&gt;LinkContents&lt;/em&gt;, avremmo duvuto scrivere:&lt;/p&gt;&lt;em&gt; var coll = from c in context.BaseContents.OfType&amp;lt;TestEntitiesModel.&lt;strong&gt;Link&lt;/strong&gt;Contents&amp;gt;()&lt;/em&gt;&lt;br /&gt; &lt;p&gt;Oltre al &lt;em&gt;Table Per Hierarchy (Single Table Inheritance)&lt;/em&gt; l'&lt;em&gt;EntityFramework&lt;/em&gt; mette a disposizione altri due tipi di &lt;em&gt;inheritance&lt;/em&gt;:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;em&gt;Table Per Type&lt;/em&gt; &lt;li&gt;&lt;em&gt;Table Per Concrete Class&lt;/em&gt; &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Ma le cosa iniziano a complicarsi un po' con l'editor di VS2008.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/Visual_Studio/&quot; rel=&quot;tag&quot;&gt;Visual Studio&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2377/Entity-Framework-Ereditarieta-Single-Table-Inheritance.aspx"/><issued>2008-08-30T15:07:56+00:00</issued><modified>2008-08-30T15:07:56+00:00</modified><slash:comments>2</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2377/Entity-Framework-Ereditarieta-Single-Table-Inheritance.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2377.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2377</trackback:ping></entry><entry><title>L'entity Framework e i vincoli FOREIGN KEY</title><id>http://blogs.aspitalia.com/az/post2374/Lentity-Framework-Vincoli-FOREIGN-KEY.aspx</id><created>2008-08-28T07:12:13+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2374' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;L'&lt;em&gt;entity framework&lt;/em&gt; rende felice. Ti fa vedere il mondo dei database sotto un'altra ottica. Le complicazioni create dai soliti esperti di struttura dei database fanno ora sorridere, anzi, li si incita a complicare maggiormente la struttura delle tabella per normalizzazioni fino al quinto livello.&lt;/p&gt; &lt;p&gt;-&lt;em&gt; Il terzo livello basta! &lt;br /&gt;&lt;/em&gt;- &lt;em&gt;No, andiamo fino al quinti livello di normalizzazione!&lt;/em&gt; - possono ora affermare i &lt;em&gt;dev &lt;/em&gt;sorseggiando un caff&amp;#232; alle loro spalle.&lt;/p&gt; &lt;p&gt;A parte queste &lt;em&gt;ciance&lt;/em&gt;, una delle attenzioni che si devono avere quando si usa l'&lt;em&gt;Entity Framework&lt;/em&gt; &amp;#232; quando si cancellano delle &lt;em&gt;entity&lt;/em&gt; dal database quando sono in gioco &lt;em&gt;Foreign key&lt;/em&gt; e amenit&amp;#224; simili. Inoltre, la cancellazione di una entit&amp;#224; non elimina - giustamente - di suo eventuali propriet&amp;#224; collegate uno-a-uno con un'altra tabella (sempre che sul db non ci siano regole varie, ma in questo caso di deve prestare attenzione, perch&amp;#233; la cache interna dell'&lt;em&gt;Entity Framework&lt;/em&gt; la vedr&amp;#224; ancora presente). Buona regola, nel caso di voler cancellare tutti i record coinvolti in una entit&amp;#224;, scrivere:&lt;/p&gt; &lt;p&gt;&lt;em&gt;using (pubsModel.pubsEntities2 context = new pubsModel.pubsEntities2()) &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var padre = context.Canc_Padre.Include(&amp;quot;Canc_Figlia&amp;quot;).First(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var figlia = padre.Canc_Figlia; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.DeleteObject(figlia); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.DeleteObject(padre); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.SaveChanges(); &lt;br /&gt;} &lt;/em&gt;&lt;/p&gt; &lt;p&gt;In questo caso le tabelle di chiamano &lt;em&gt;Canc&lt;/em&gt;_&lt;em&gt;Padre&lt;/em&gt; e &lt;em&gt;Canc&lt;/em&gt;_&lt;em&gt;Figlia&lt;/em&gt;. L'ordine di cancellazione dev'essere anche quello mostrato (prima la tabella figlia e poi la padre), perch&amp;#233; la cancellazione dell'entit&amp;#224; padre farebbe perdere il collegamento con il record da cancellare con la necessit&amp;#224; di una nuova query di &lt;em&gt;select&lt;/em&gt; di ricerca. &lt;/p&gt; &lt;p&gt;Ma nel caso delle relazioni molti-a-molti? Prendiamo d'esempio un classico schema con tre tabelle: &lt;/p&gt; &lt;ol&gt; &lt;li&gt;authors &lt;/li&gt; &lt;li&gt;books &lt;/li&gt; &lt;li&gt;authorsbooks&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Le prime due sono le classiche tabelle che conterranno i dati, la terza quella che collega i dati delle due.&lt;/p&gt; &lt;p&gt;Scrivendo questo codice:&lt;/p&gt; &lt;p&gt;&lt;em&gt;using (pubsModel.pubsEntities2 context = new pubsModel.pubsEntities2()) &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var coll = (from au in context.authors &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where au.name==&amp;quot;...&amp;quot; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; select au).First(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.DeleteObject(coll); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.SaveChanges(); &lt;br /&gt;} &lt;/em&gt;&lt;/p&gt; &lt;p&gt;Otterremo il classico errore:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;L'istruzione DELETE &amp;#232; in conflitto con il vincolo REFERENCE &amp;quot;FK_authors_books_authors&amp;quot;. Il conflitto si &amp;#232; verificato nella tabella &amp;quot;dbo.authorsbooks&amp;quot;, column 'id_author' del database &amp;quot;pubs&amp;quot;.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Per evitare questo problema, cio&amp;#232; cancellare il record dalla tabella &lt;em&gt;authors&lt;/em&gt; e ogni suo riferimento dalla tabella &lt;em&gt;authorsbooks&lt;/em&gt;, dovremo invece scrivere:&lt;/p&gt; &lt;em&gt;using (pubsModel.pubsEntities2 context = new pubsModel.pubsEntities2()) &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var coll = (from au in context.authors.&lt;strong&gt;Include(&amp;quot;books&amp;quot;)&lt;/strong&gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where au.name==&amp;quot;...&amp;quot; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; select au).First(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.DeleteObject(coll); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.SaveChanges(); &lt;br /&gt;} &lt;/em&gt; &lt;p&gt;Se volessimo cancellare anche il record in &lt;em&gt;book&lt;/em&gt;, dovremo fare come sopra: recuperata l'&lt;em&gt;entity&lt;/em&gt; usare il &lt;em&gt;DeleteObject&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;PS: ieri sera ho dovuto aspettare venti minuti il pullman per tornare a casa.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/Database/&quot; rel=&quot;tag&quot;&gt;Database&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2374/Lentity-Framework-Vincoli-FOREIGN-KEY.aspx"/><issued>2008-08-28T09:12:13+00:00</issued><modified>2008-08-28T09:12:13+00:00</modified><slash:comments>6</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2374/Lentity-Framework-Vincoli-FOREIGN-KEY.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2374.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2374</trackback:ping></entry><entry><title>Data Service Viewer</title><id>http://blogs.aspitalia.com/az/post2373/Data-Service-Viewer.aspx</id><created>2008-08-28T07:09:20+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2373' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Interessante questo &lt;a title=&quot;link esterno&quot; href=&quot;http://weblogs.asp.net/vardi/archive/2008/08/27/ado-net-data-services-viewer-tool.aspx&quot;&gt;tool&lt;/a&gt;. Anche se &lt;a title=&quot;link esterno&quot; href=&quot;http://astoria.mslivelabs.com/&quot;&gt;Astoria&lt;/a&gt; &amp;#232; una tecnologia che mi mette parecchi dubbi (dubbi che non voglio per ora divulgare qui) la trovo interessante. E se c'&amp;#232; un tool che permette di provare le richieste http in modo facile e che ti d&amp;#224; anche una mano, ben venga.&lt;/p&gt; &lt;p&gt;E' un exe scritto in .net. Alla prima richiesta richiede l'endpoint dove astoria &amp;#232; in attesa, per esempio:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://localhost:1035/websiteentity2/webdataservice.svc&quot;&gt;http://localhost:1035/WebSiteEntity2/WebDataService.svc&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Nel codice di questo &lt;em&gt;ado.net web data service&lt;/em&gt;, &amp;#232; necessario obbligare quali entit&amp;#224; possono essere utilizzate e come:&lt;/p&gt; &lt;p&gt;&lt;em&gt;public class WebDataService : DataService&amp;lt;pubsModel.pubsEntities2&amp;gt; &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static void InitializeService(IDataServiceConfiguration config) &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; { &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; config.SetEntitySetAccessRule(&amp;quot;*&amp;quot;, EntitySetRights.All); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; config.SetServiceOperationAccessRule(&amp;quot;*&amp;quot;, ServiceOperationRights.All); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;br /&gt;}&lt;/em&gt; &lt;/p&gt; &lt;p&gt;Qui ho specificato che &amp;#232; possibile operare su tutte le entit&amp;#224; e che posso farci di tutto tra queste scelte possibili.&lt;/p&gt; &lt;p&gt;Ok, avviata la web application con questo nuovo oggetto, possiamo utilizzare il tool prima citato che il nome significativo &amp;quot;Data service viewer&amp;quot;. Inserito l'endpoint, ecco la schermata:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;459&quot; alt=&quot;data service viewer&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/dataserviceviewer_80c0/immagine%202_3.gif&quot; width=&quot;524&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;Ma l'utilit&amp;#224; vera &amp;#232; nella possibilit&amp;#224; di provare le query avendo il supporto per l'intellisense durante la scrittura:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://blogs.aspitalia.com/img/andrewz/dataserviceviewer_80c0/immagine%201_2.gif&quot;&gt;&lt;img height=&quot;388&quot; alt=&quot;data service viewer&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/dataserviceviewer_80c0/immagine%201_thumb.gif&quot; width=&quot;523&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Qui si scopre un piccolo problema. L'elenco delle scelte possibile &amp;#232; selezionabile con i tasti cursore e la scelta &amp;#232; selezionabile solo con il tasto invio e con il mouse mentre il tasto tab manda al pulsante per l'esecuzione della query.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2373/Data-Service-Viewer.aspx"/><issued>2008-08-28T09:09:20+00:00</issued><modified>2008-08-28T09:09:20+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2373/Data-Service-Viewer.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2373.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2373</trackback:ping></entry><entry><title>Lazy Loading con l'Entity Framework</title><id>http://blogs.aspitalia.com/az/post2372/Lazy-Loading-Entity-Framework.aspx</id><created>2008-08-27T11:33:57+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2372' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Anche se qualcuno afferma il contrario, non cito la fonte, abbiamo a disposizione pi&amp;#249; metodi per caricare entit&amp;#224; collegate. In tutti questi post dedicati all'&lt;em&gt;Entity Framework&lt;/em&gt; ho fatto sempre esempio che riguardavano pi&amp;#249; tabelle (~entit&amp;#224;) collegate.&lt;/p&gt; &lt;p&gt;Possiamo fare in modo che sia lo stesso &lt;em&gt;Entity Framework&lt;/em&gt; a caricare con una query il tutto grazie a Include:&lt;/p&gt; &lt;p&gt;&lt;em&gt;var coll=from c in EntityContext.Articles.Include(&amp;quot;Authors&amp;quot;) &lt;br /&gt;select c; &lt;br /&gt;foreach (var item in coll) &lt;br /&gt;{ &lt;br /&gt;Response.Write(item.Title); &lt;br /&gt;Response.Write(item.Authors.Name); &lt;br /&gt;}&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Oppure possiamo forzare il caricamente delle entit&amp;#224; collegate, in questo caso &lt;em&gt;Authors&lt;/em&gt;, ad ogni richiesta della stessa:&lt;/p&gt; &lt;p&gt;&lt;em&gt;var coll=from c in EntityContext.Articles &lt;br /&gt;select c; &lt;br /&gt;foreach (var item in coll) &lt;br /&gt;{ &lt;br /&gt;Response.Write(item.Title); &lt;br /&gt;if (item.AuthorsReference.IsLoaded) // Controlla se gi&amp;#224; presente in memoria &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Response.Write(item.AuthorsReference.Value.Name); &lt;br /&gt;else &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; item.AuthorsReference.Load(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Response.Write(item.Authors.Name); &lt;br /&gt;} &lt;br /&gt;}&lt;/em&gt;&lt;/p&gt; &lt;p&gt;In quest'ultimo caso all'inizio viene eseguita una query che richiede solo la lista degli &lt;em&gt;Articles&lt;/em&gt;. Quindi viene verificato che l'entit&amp;#224; per gli &lt;em&gt;Authors&lt;/em&gt; non sia gi&amp;#224; presente in memoria; se presente la visualizza direttamente, altrimenti esegue una query al database.&lt;/p&gt; &lt;p&gt;Il numero di query inviate al database &amp;#232; N+(numero di autori richiesti differenti). Ipoteticamente, se tutti gli articoli fossero collegati ad un solo autore, il numero di query inviate al database sarebbero due.&lt;/p&gt; &lt;p&gt;PS: scusate la brevit&amp;#224; ma il tempo &amp;#232; tiranno. O Tir&lt;em&gt;&amp;#224;&lt;/em&gt;no?&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2372/Lazy-Loading-Entity-Framework.aspx"/><issued>2008-08-27T13:33:57+00:00</issued><modified>2008-08-27T13:33:57+00:00</modified><slash:comments>6</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2372/Lazy-Loading-Entity-Framework.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2372.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2372</trackback:ping></entry><entry><title>4 desktop virtuali su Windows</title><id>http://blogs.aspitalia.com/az/post2371/Desktop-Virtuali-Windows.aspx</id><created>2008-08-26T12:01:02+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2371' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Una peculiarit&amp;#224; che ho sempre apprezzato nei desktop manager di Linux &amp;#232; la possibilit&amp;#224; di dividere la zona di lavoro su pi&amp;#249; desktop virtuali. &lt;a title=&quot;link esterno&quot; href=&quot;http://blogs.dotnethell.it/windowsvista/post_14028.aspx&quot;&gt;Leggo&lt;/a&gt; ora che &amp;#232; presente questo &lt;a title=&quot;link esterno&quot; href=&quot;http://technet.microsoft.com/en-us/sysinternals/cc817881.aspx&quot;&gt;tool&lt;/a&gt; che lo permette anche su Windows. Scaricato e avviato. Funziona discretamente, ed &amp;#232; veloce e &lt;em&gt;pesa&lt;/em&gt; poco. Il problema &amp;#232; un altro: non permette i passaggi di finestre tra un desktop all'altro con la stessa facilit&amp;#224; che permette Gnome o Kde: vengono s&amp;#236; create pi&amp;#249; arie di lavoro, ma queste non sembrano poter comunicare.&lt;/p&gt; &lt;p&gt;Peccato.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2371/Desktop-Virtuali-Windows.aspx"/><issued>2008-08-26T14:01:02+00:00</issued><modified>2008-08-26T14:01:02+00:00</modified><slash:comments>12</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2371/Desktop-Virtuali-Windows.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2371.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2371</trackback:ping></entry><entry><title>A volte ritornano... GridView vs Repeater vs ListView vs Custom</title><id>http://blogs.aspitalia.com/az/post2370/Volte-Ritornano.-GridView-Repeater-ListView-Custom.aspx</id><created>2008-08-26T07:20:37+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2370' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;&lt;a href=&quot;http://blogs.aspitalia.com/az/post549/ancora-prestazioni-datagrid-datalist-repeater-.aspx&quot;&gt;Sono passati anni&lt;/a&gt;? Parecchio tempo fa avevo confrontato le prestazioni nel binding dei dati tra i pi&amp;#249; noti webcontrol. Ecco un refresh, questa volta con il Framework 3.5 e con lo scontro tra:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Gridview &lt;/li&gt; &lt;li&gt;Repeater &lt;/li&gt; &lt;li&gt;ListView &lt;/li&gt; &lt;li&gt;Custom code&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Chiunque un po' smaliziato con il .net sapr&amp;#224; gi&amp;#224; chi vince e chi &amp;#232; il peggiore tra questi. Ma per i novizi &amp;#232; sempre meglio saperlo. Innanzitutto, il codice per il popolamento delle tabelle html &amp;#232; il seguente:&lt;/p&gt; &lt;p&gt;&lt;em&gt;List&amp;lt;Person&amp;gt; p; &lt;br /&gt;p = new List&amp;lt;Person&amp;gt;(200); &lt;br /&gt;for (int i = 0; i &amp;lt; 200; i++) &lt;br /&gt;&amp;#160; p.Add(new Person { Id=i, Age=i, Description=&amp;quot;Desc &amp;quot;+i.ToString(), Name=&amp;quot;Name &amp;quot;+i.ToString() }); &lt;/em&gt;&lt;/p&gt; &lt;p&gt;Il &lt;em&gt;gridview&lt;/em&gt; crea la table html con questo codice:&lt;/p&gt; &lt;p&gt;&lt;em&gt;&amp;lt;asp:GridView ID=&amp;quot;gw1&amp;quot; EnableViewState=&amp;quot;false&amp;quot; runat=&amp;quot;server&amp;quot; AutoGenerateColumns=&amp;quot;false&amp;quot;&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Columns&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:BoundField DataField=&amp;quot;id&amp;quot; /&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:BoundField DataField=&amp;quot;name&amp;quot; /&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:BoundField DataField=&amp;quot;age&amp;quot; /&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:BoundField DataField=&amp;quot;description&amp;quot; /&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/Columns&amp;gt; &lt;br /&gt;&amp;lt;/asp:GridView&amp;gt; &lt;/em&gt;&lt;/p&gt; &lt;p&gt;Per il &lt;em&gt;repeater&lt;/em&gt; abbiamo: &lt;/p&gt; &lt;p&gt;&lt;em&gt;&amp;lt;asp:Repeater ID=&amp;quot;rp1&amp;quot; runat=&amp;quot;server&amp;quot; EnableViewState=&amp;quot;false&amp;quot;&amp;gt; &lt;br /&gt;&amp;lt;HeaderTemplate&amp;gt;&amp;lt;table border=&amp;quot;1&amp;quot;&amp;gt;&amp;lt;/HeaderTemplate&amp;gt; &lt;br /&gt;&amp;lt;FooterTemplate&amp;gt;&amp;lt;/table&amp;gt;&amp;lt;/FooterTemplate&amp;gt; &lt;br /&gt;&amp;lt;ItemTemplate&amp;gt; &lt;br /&gt;&amp;lt;tr&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# Eval(&amp;quot;id&amp;quot;) %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# Eval(&amp;quot;name&amp;quot;) %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# Eval(&amp;quot;age&amp;quot;) %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# Eval(&amp;quot;description&amp;quot;) %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;lt;/tr&amp;gt; &lt;br /&gt;&amp;lt;/ItemTemplate&amp;gt; &lt;br /&gt;&amp;lt;/asp:Repeater&amp;gt; &lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;M&lt;/em&gt;a siccome vogliamo ottimizzare un po', possiamo scrivere: &lt;/p&gt; &lt;p&gt;&lt;em&gt;&amp;lt;tr&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# ((Person)Container.DataItem).Id %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# ((Person)Container.DataItem).Name %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# ((Person)Container.DataItem).Age %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# ((Person)Container.DataItem).Description %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;lt;/tr&amp;gt; &lt;/em&gt;&lt;/p&gt; &lt;p&gt;Ecco il &lt;em&gt;ListView&lt;/em&gt;, semplice: &lt;/p&gt; &lt;p&gt;&lt;em&gt;&amp;lt;asp:ListView ID=&amp;quot;lw1&amp;quot; runat=&amp;quot;server&amp;quot; EnableViewState=&amp;quot;false&amp;quot;&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;LayoutTemplate&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;table border=&amp;quot;1&amp;quot;&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:Panel ID=&amp;quot;itemPlaceholder&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/table&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/LayoutTemplate&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;ItemTemplate&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;tr&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# Eval(&amp;quot;id&amp;quot;) %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# Eval(&amp;quot;name&amp;quot;) %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# Eval(&amp;quot;age&amp;quot;) %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# Eval(&amp;quot;description&amp;quot;) %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/tr&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/ItemTemplate&amp;gt; &lt;br /&gt;&amp;lt;/asp:ListView&amp;gt;&lt;/em&gt;&amp;#160;&lt;/p&gt; &lt;p&gt;E ottimizzato: &lt;/p&gt; &lt;p&gt;&lt;em&gt;&amp;lt;ItemTemplate&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;tr&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# ((Person)Container.DataItem).Id %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# ((Person)Container.DataItem).Name %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# ((Person)Container.DataItem).Age %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;&amp;lt;%# ((Person)Container.DataItem).Description %&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/tr&amp;gt; &lt;br /&gt;&amp;lt;/ItemTemplate&amp;gt; &lt;/em&gt;&lt;/p&gt; &lt;p&gt;E infine creiamo la griglia da codice con un banale &lt;em&gt;StringBuilder&lt;/em&gt; da codice: &lt;/p&gt; &lt;p&gt;&lt;em&gt;var sb = new StringBuilder(10000); &lt;br /&gt;sb.Append(&amp;quot;&amp;lt;table border='1'&amp;gt;&amp;quot;); &lt;br /&gt;for (int i = 0; i &amp;lt; p.Count; i++) &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb.Append(&amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;quot;); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb.Append(p[i].Id); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb.Append(&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb.Append(p[i].Name); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb.Append(&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb.Append(p[i].Age); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb.Append(&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb.Append(p[i].Description); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb.Append(&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;); &lt;br /&gt;} &lt;br /&gt;sb.Append(&amp;quot;&amp;lt;/table&amp;gt;&amp;quot;); &lt;br /&gt;pn1.Controls.Add(new LiteralControl(sb.ToString())); &lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;pn1&lt;/em&gt; &amp;#232; un &lt;em&gt;panel&lt;/em&gt;. Ma vediamo le prestazioni (medie): &lt;/p&gt; &lt;table cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;400&quot; border=&quot;1&quot;&gt;&lt;tbody&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;GridView&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;strong&gt;&lt;em&gt;0.122s&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;Repeater&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;0.058s&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;Repeater ottimizzato&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;0.046s&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;ListView&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;0.059s&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;ListView ottimizzato&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;0.047s&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;Custom code&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;&lt;em&gt;&lt;strong&gt;0.006s&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;A parte la tabella scritta con lo &lt;em&gt;StringBuilder&lt;/em&gt; che mediamente risulta otto volte pi&amp;#249; veloce del &lt;em&gt;ListView&lt;/em&gt; e del &lt;em&gt;Repeater&lt;/em&gt;, la sorpresa &amp;#232; proprio il &lt;em&gt;ListView&lt;/em&gt; che risulta veloce quanto il &lt;em&gt;Repeater&lt;/em&gt;. In poche parole? Il &lt;em&gt;DataGrid&lt;/em&gt;, &lt;em&gt;DataList&lt;/em&gt;, &lt;em&gt;DataGrid&lt;/em&gt; e &lt;em&gt;Repeater&lt;/em&gt; sono diventati obsoleti e inutili dato il &lt;em&gt;ListView&lt;/em&gt; non solo sostituisce in tutto questi webcontrol, ma ha prestazioni pi&amp;#249; che buone.&amp;#160;&amp;#160; &lt;/p&gt; &lt;p&gt;Inoltre, per avere un discreto guadagno, anche la visualizzazione con il &lt;em&gt;casting&lt;/em&gt; di tipo nella colonna, invece dell'&lt;em&gt;Eval&lt;/em&gt;, &amp;#232; consigliato.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/ASP.NET/&quot; rel=&quot;tag&quot;&gt;ASP.NET&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/ASP.NET_2.0/&quot; rel=&quot;tag&quot;&gt;ASP.NET 2.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/ASP.NET_3.5/&quot; rel=&quot;tag&quot;&gt;ASP.NET 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Databinding/&quot; rel=&quot;tag&quot;&gt;Databinding&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Datagrid/&quot; rel=&quot;tag&quot;&gt;Datagrid&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/GridView/&quot; rel=&quot;tag&quot;&gt;GridView&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2370/Volte-Ritornano.-GridView-Repeater-ListView-Custom.aspx"/><issued>2008-08-26T09:20:37+00:00</issued><modified>2008-08-26T09:20:37+00:00</modified><slash:comments>18</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2370/Volte-Ritornano.-GridView-Repeater-ListView-Custom.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2370.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2370</trackback:ping></entry><entry><title>L'Entity Framework e l'ObjectDataSource</title><id>http://blogs.aspitalia.com/az/post2369/LEntity-Framework-ObjectDataSource.aspx</id><created>2008-08-24T19:26:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2369' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Anche se con l'SP1 del Framework 3.5 &#232; stato introdotto il nuovo &lt;em&gt;EntityDataSource&lt;/em&gt; per collegare direttamente questi nuovi oggetti a web control come il &lt;em&gt;ListView&lt;/em&gt; o il &lt;em&gt;GridView&lt;/em&gt;, l'utilizzo dell'&lt;em&gt;ObjectDataSource&lt;/em&gt; rimane sempre la soluzione migliore: come dice &lt;a href=&quot;http://blogs.aspitalia.com/daniele&quot;&gt;Daniele&lt;/a&gt;, i &lt;em&gt;datasource&lt;/em&gt; come l'&lt;em&gt;SqlDataSource&lt;/em&gt; e compagnia bella sono solo veramente utili per le demo.&lt;/p&gt;&lt;p&gt;Di base non ci sono problemi. Solo di base per&#242;. Quando si cerca di fare qualcosa di pi&#249; complesso saltano sempre fuori casini vari. Messo nella pagina un &lt;em&gt;ListView&lt;/em&gt; collegato ad un bel &lt;em&gt;ObjectDataSource&lt;/em&gt; che utilizza una classe apposita che ritorna le entit&#224; (nel mio caso con l'ausilio dell'&lt;em&gt;Entity Framework&lt;/em&gt;) non ci sono problemi: persino altre entit&#224; memorizzate in propriet&#224; vengono visualizzate correttamente. Come nell'esempio gi&#224; &lt;a href=&quot;http://blogs.aspitalia.com/az/post2361/entity-framework-sql-generato.aspx&quot;&gt;visto&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;gridview&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/entityframeworkelsqlgenerato_adf2/image_1.png&quot; /&gt; &lt;/p&gt;&lt;p&gt;I problemi nascono quando entrano in gioco gli update e gli insert. Come scritto sopra, di base, cio&#232; con propriet&#224; con tipi non complessi, non ci sono problemi. Definendo nell'&lt;em&gt;InsertMethod&lt;/em&gt; dell'&lt;em&gt;ObjectDataSource&lt;/em&gt; una nostra funzione come la seguente, tutto funziona:&lt;/p&gt;&lt;p&gt;&lt;em&gt;[System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Insert)]&lt;br /&gt;public static void InsertAuthor(Author author)&lt;br /&gt;{&lt;br /&gt;using (TestEntitiesModel.TestEntitiesCode context = new TestEntitiesModel.TestEntitiesCode())&lt;br /&gt;{&lt;br /&gt;context.addAuthors(author);&lt;br /&gt;context.SaveChanges();&lt;br /&gt;} &lt;br /&gt;}&lt;/em&gt; &lt;/p&gt;&lt;p&gt;Che bello! Eh s&#236;, ma l'entit&#224; qui trattata ha anche come propriet&#224; la collection di &lt;em&gt;Book&lt;/em&gt; collegati all'autore secondo il seguente schema: &lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;entity framework&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/sqlserver2008evisualstudio2008sp1_10f47/image_6.png&quot; /&gt; &lt;/p&gt;&lt;p&gt;Per visualizzare il tutto in modalit&#224; &lt;em&gt;edit&lt;/em&gt; si incotrano le prime rogne ma risolvibile. Ma cosa viene passato al metodo &lt;em&gt;InsertAuthor&lt;/em&gt; prima mostrato? Tutto, tranne, ovviamente, eventuli aggiunte ai &lt;em&gt;book&lt;/em&gt;. Qui l'esempio &#232; un po' forzato, ma un caso reale potrebbe essere la creazione di un nuovo utente e il collegamento ad esso di una o pi&#249; role per autorizzazione varie (visualizzate in modalit&#224; &lt;em&gt;edit&lt;/em&gt; come lista con &lt;em&gt;checkbox&lt;/em&gt;). &lt;/p&gt;&lt;p&gt;Come inviare il tutto in modo corretto a quella funzione o quasi? &lt;/p&gt;&lt;p&gt;Io ho solo trovato un espediente, ma spero ci siano soluzioni pi&#249; semplici che finora mi sono sfuggite. Utilizzando l'evento &lt;em&gt;On_ItemInserting&lt;/em&gt; dell'&lt;em&gt;ListView&lt;/em&gt; possiamo forza l'aggiunta di tutte le informazioni utili: &lt;/p&gt;&lt;p&gt;&lt;em&gt;protected void lw_authors_ItemInserting(object sender, ListViewInsertEventArgs e)&lt;br /&gt;{&lt;br /&gt;// In Values troviamo tutti i valori letti dal objectdatasource (BoundColumn, Bind, ecc...)&lt;br /&gt;// Inserisce un campo aggiuntivo perla data presente nel db ma non del ListView&lt;br /&gt;e.Values.Add(&amp;quot;CreationData&amp;quot;, DateTime.Now);&lt;br /&gt;var books = new System.Data.Objects.DataClasses.EntityCollection&lt;book /&gt;();&lt;br /&gt;// Metodi che richiedono le entit&#224; da collegare&lt;br /&gt;books.Add( AZ.GetBookFromId(1) );&lt;br /&gt;books.Add( AZ.GetBookFromId(2) );&lt;br /&gt;e.Values.Add(&amp;quot;Books&amp;quot;, auths);&lt;br /&gt;} &lt;/em&gt;&lt;/p&gt;&lt;p&gt;Innanzitutto, l'&lt;em&gt;objectdatasource&lt;/em&gt; espone la connection come &lt;em&gt;EntityConnection&lt;/em&gt;, quindi perch&#233; possa essere riconosciuta dobbiamo inserire tutti gli item selezionati in questa collection. Sembra tutto ok, in questo modo all'evento di inserimento &lt;em&gt;dovrebbe&lt;/em&gt; essere passato il tutto correttamente. Dovrebbe! Richiamato questo codice si ha come output un errore chiarissimo in merito proprio al momento dell'&lt;em&gt;Add&lt;/em&gt;:&lt;/p&gt;&lt;p&gt;&lt;i&gt;&lt;strong&gt;The object could not be added to the EntityCollection or EntityReference. An object that is attached to an ObjectContext cannot be added to an EntityCollection or EntityReference that is not associated with a source object.&lt;/strong&gt;&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Allora ecco l'&lt;em&gt;escamotage&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;protected void lw_users_ItemInserting(object sender, ListViewInsertEventArgs e)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;...&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var books = new System.Data.Objects.DataClasses.EntityCollection&amp;lt;Book&amp;gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; books.Add(new&amp;nbsp;Book { Id = 1 });&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; books.Add(new&amp;nbsp;Book { Id = 2 });&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; e.Values.Add(&quot;Books&quot;, auths);&lt;br&gt;} &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Creo due nuove classi &lt;em&gt;Book&lt;/em&gt; dove inserisco gli &lt;em&gt;Id&lt;/em&gt; dei valori selezionati nell'interfaccia grafica (qui inseriti da codice per rendere il tutto pi&#249; semplice). Ora il codice per l'inserimento dovrebbe accettare anche questi dati aggiuntivi, ma ecco il secondo problema della giornata: quelle entit&#224; verrebbero trattate come nuovi oggetti e inseriti nuovamente nel database. Ecco dunque l'ultima modifica al codice, questa volta nella funzione di inserimento:&lt;/p&gt;&lt;em&gt;[System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Insert)]&lt;br&gt;public static void InsertAuthor(Author author)&lt;br&gt;{&lt;br&gt;&amp;nbsp;using (TestEntitiesModel.TestEntitiesCode context = new TestEntitiesModel.TestEntitiesCode())&lt;br&gt;&amp;nbsp;{&lt;br&gt;&amp;nbsp; var coll = user.Books.Select(r =&amp;gt; r.Id).ToArray&amp;lt;int&amp;gt;();&lt;br&gt;&amp;nbsp; user.Books.Clear();&lt;br&gt;&amp;nbsp; foreach (var item in coll)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; user.Books.Add( context.Books.Where( r=&amp;gt;r.Id==item ).FirstOrDefault() );&lt;br&gt;&amp;nbsp; // Oppure&lt;br&gt;&amp;nbsp; // foreach (var item in coll)&lt;br&gt;&amp;nbsp;&amp;nbsp;//&amp;nbsp; user.Books.Add(&amp;nbsp;context.GetObjectbyKey( item ) );&lt;br&gt;&amp;nbsp;&amp;nbsp;context.addAuthors(author);&lt;br&gt;&amp;nbsp; context.SaveChanges();&lt;br&gt;&amp;nbsp;} &lt;br&gt;}&lt;/em&gt; 
&lt;p&gt;E tutto funziona correttamente. Ma spero ci siano soluzioni pi&#249; immediate e semplici. Vero? Ditemi di s&#236;! :(&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2369/LEntity-Framework-ObjectDataSource.aspx"/><issued>2008-08-24T21:26:00+00:00</issued><modified>2008-08-24T21:26:00+00:00</modified><slash:comments>15</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2369/LEntity-Framework-ObjectDataSource.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2369.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2369</trackback:ping></entry><entry><title>SP vs Linq vs Entity Framework in scrittura</title><id>http://blogs.aspitalia.com/az/post2368/SP-Linq-Entity-Framework-Scrittura.aspx</id><created>2008-08-22T21:11:44+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2368' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;La sola sicurezza che avevo era &lt;strong&gt;di quanto&lt;/strong&gt; Linq e l'Entity Framework fossero pi&#249; lenti. Mi preparo un banale test per l'inserimento di un buon numero di record in un database Sql server 2005 per un benchmark personale. Creo due tabelle collegate dalla struttura molto semplice:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;320&quot; alt=&quot;struttura tabelle&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/spvslinqvsentityframeworkinscrittura_141e2/image_1.png&quot; width=&quot;358&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p&gt;Il mio test &#232; molto banale: creare un array casuale di 100 padri, e ogni padre un array casuale di 100 figli. Gli sfidanti e le armi utilizzate sono i seguenti:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Collection tradizionale e stored procedure (una per ogni tabella) richiamata con il &lt;em&gt;Prepare&lt;/em&gt; del &lt;em&gt;Command&lt;/em&gt; per il massimo delle prestazioni.&lt;/li&gt; &lt;li&gt;Collection inserita direttamente in un DataContext creato da Visual Studio 2008.&lt;/li&gt; &lt;li&gt;Collection inserita direttamente nelle collection create dall'Entity Framework.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Ecco di seguito il DataContext usato da Linq:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;298&quot; alt=&quot;datacontext di linq&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/spvslinqvsentityframeworkinscrittura_141e2/image_3.png&quot; width=&quot;236&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p&gt;E l'&lt;em&gt;Entity Framework&lt;/em&gt; creato sempre da VS2008:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;352&quot; alt=&quot;l'entity framework creato da vs2008&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/spvslinqvsentityframeworkinscrittura_141e2/image_5.png&quot; width=&quot;182&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p&gt; Avvio pi&#249; volte i test per ogni tecnologia utilizzata. La media &#232; la seguente:&lt;/p&gt; &lt;table cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;400&quot; border=&quot;1&quot; unselectable=&quot;on&quot;&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td  width=&quot;133&quot;&gt;&lt;strong&gt;Stored procedure&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;133&quot;&gt;&lt;strong&gt;Linq to Sql&lt;/strong&gt;&lt;/td&gt; &lt;td  width=&quot;133&quot;&gt;&lt;strong&gt;Entity Framework&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;133&quot;&gt;6.75&lt;em&gt;s&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;133&quot;&gt;20.60&lt;em&gt;s&lt;/em&gt;&lt;/td&gt; &lt;td  width=&quot;133&quot;&gt;12.93&lt;em&gt;s&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Sulla maggiori performance dell'inserimento diretto da codice con le &lt;em&gt;stored procedure&lt;/em&gt;, come gi&#224; detto, non ne avevo il minimo dubbio: il tutto &#232; ottimizzato al meglio, ed ho cercato anche da codice di ottimizzare il pi&#249; possibile la creazione di oggetti e il passaggio di parametri. La delusione &#232; stata invece per Linq, che le prende sonoramente anche dall'&lt;em&gt;Entity Framework&lt;/em&gt; che si dimostra molto pi&#249; efficiente del tradizionale &lt;em&gt;Linq to Sql&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;Leggendo con il Profiler le query inviate da &lt;em&gt;Linq to Sql&lt;/em&gt; e dall'&lt;em&gt;Entity Framework&lt;/em&gt;, si notano alcune differenze nelle query di inserimento create:&lt;/p&gt; &lt;p&gt;&lt;em&gt;-- Linq to Sql&lt;br /&gt;-- Inserimento nella tavella 'Padri'&lt;br /&gt;exec sp_executesql N'INSERT INTO [dbo].[Padri]([NomePadre])&lt;br /&gt;VALUES (@p0) &lt;br /&gt;SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]',N'@p0 nvarchar(7)',@p0=N'Padre 1'&lt;br /&gt;--&lt;br /&gt;-- Inserimento nella tabella 'Figli'&lt;br /&gt;exec sp_executesql N'INSERT INTO [dbo].[Figli]([IdPadre], [NomeFiglio])&lt;br /&gt;VALUES (@p0, @p1) &lt;br /&gt;SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]',N'@p0 int,@p1 nvarchar(9)',@p0=400,@p1=N'Padre 1 1'&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;---- Entity Framework&lt;br /&gt;-- Inserimenti nella tabella 'Padri'&lt;br /&gt;exec sp_executesql N'insert [dbo].[Padri]([NomePadre])&lt;br /&gt;values (@0)&lt;br /&gt;select [Id]&lt;br /&gt;from [dbo].[Padri]&lt;br /&gt;where @@ROWCOUNT &amp;gt; 0 and [Id] = scope_identity()',N'@0 nvarchar(7)',@0=N'Padre 1'&lt;br /&gt;--&lt;br /&gt;-- Inserimento nella tabella 'Figli'&lt;br /&gt;exec sp_executesql N'insert [dbo].[Figli]([IdPadre], [NomeFiglio])&lt;br /&gt;values (@0, @1)&lt;br /&gt;select [Id]&lt;br /&gt;from [dbo].[Figli]&lt;br /&gt;where @@ROWCOUNT &amp;gt; 0 and [Id] = scope_identity()',N'@0 int,@1 nvarchar(9)',@0=1600,@1=N'Padre 1 1'&lt;/em&gt;&lt;/p&gt; &lt;p&gt;La cosa che salta all'occhio subito &#232; il differente modo di prendere l'&lt;em&gt;id&lt;/em&gt; del record appena inserito e sembra, e lo ripeto, sembra, che sia pi&#249; performante quello utilizzato dall'Entity Framework anche se, la differenze in peggio tra le due tecnolgie, potrebbero essere invece a livello di codice del Framework nelle sue creazioni delle query.&lt;/p&gt; &lt;p&gt;Ora &#232; tardi per investigare oltre. Ho fatto appena un viaggio di circa tre ore di pullman e sono stanco... Ma prima, si possono tirare conclusioni? Il mio test pu&#242; essere un caso reale di codice? La stanchezza mi sta spegnendo la ragione... mi fermo qui&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/ADO.NET_Entity_Framework/&quot; rel=&quot;tag&quot;&gt;ADO.NET Entity Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ/&quot; rel=&quot;tag&quot;&gt;LINQ&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Database/&quot; rel=&quot;tag&quot;&gt;Database&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2368/SP-Linq-Entity-Framework-Scrittura.aspx"/><issued>2008-08-22T23:11:44+00:00</issued><modified>2008-08-22T23:11:44+00:00</modified><slash:comments>9</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2368/SP-Linq-Entity-Framework-Scrittura.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2368.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2368</trackback:ping></entry><entry><title>Ho fatto pace con l'Entity Framework: un minimo di cache!</title><id>http://blogs.aspitalia.com/az/post2367/Fatto-Pace-Entity-Framework-Minimo-Cache.aspx</id><created>2008-08-22T12:26:34+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2367' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Nel &lt;a href=&quot;http://blogs.aspitalia.com/az/post2366/entity-framework.-minimo-cache-faceva-schifo.aspx&quot;&gt;post precedente&lt;/a&gt; riscontravo che come due richieste sulla stessa entit&amp;#224; venisse gestita dall'Entity Framework in maniera - per me - strana, o per meglio dire, non in modo ottimizzato, perch&amp;#233; eseguiva due query perfettamente identiche al database. Ovviamente, come mi ha fatto notare giustamente &lt;a href=&quot;http://blogs.aspitalia.com/daniele/&quot;&gt;Daniele&lt;/a&gt; e &lt;a href=&quot;http://blogs.aspitalia.com/ricciolo/&quot;&gt;Cristian&lt;/a&gt;, &amp;#232; un comportamento legittimo, e anzi, sarebbe stato strano se avveniva come io lo avevo immaginato.&lt;/p&gt; &lt;p&gt;Scopro solo ora che nativamente esiste una sorta di cache all'interno dell'Entity Framework, ma la cosa deve essere forzata dal programmatore. Riprendendo l'esempio del mio blog precedente, si deve scrivere:&lt;/p&gt; &lt;p&gt;&lt;em&gt;using (TestModel.TestEntities context = new TestModel.TestEntities()) &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int colore = 2; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var a = new TestModel.Articles(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Article = &amp;quot;Art3 &amp;quot; + DateTime.Now.ToString(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var c = context.Colors.Where(w =&amp;gt; w.Id == colore).First(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Colors = c; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.AddToArticles(a); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a = new TestModel.Articles(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Article = &amp;quot;Art4 &amp;quot; + DateTime.Now.ToString(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ////////////////////////////////////// &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; object obj = null; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.TryGetObjectByKey( &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new System.Data.EntityKey( &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string.Format(&amp;quot;{0}.{1}&amp;quot;, context.DefaultContainerName, &amp;quot;Colors&amp;quot;), &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Id&amp;quot;, &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; colore), out obj); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (obj != null) &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // E' presente tra gli oggetti &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; c = (TestModel.Colors)obj; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Rifaccio la query (*) &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; c = context.Colors.Where(w =&amp;gt; w.Id == colore).First(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ///////////////////////////////////// &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Colors = c; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.AddToArticles(a); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.SaveChanges(); &lt;br /&gt;}&lt;/em&gt;&lt;/p&gt; &lt;p&gt;A venirmi in aiuto ci pensa la funzione &lt;em&gt;TryGetObjectByKey&lt;/em&gt; che permette di cercare un oggetto per la sua &lt;em&gt;key&lt;/em&gt; all'interno del &lt;em&gt;context&lt;/em&gt; attuale utilizzato per l'&lt;em&gt;entity framework&lt;/em&gt;. La sintassi &amp;#232; un po' intricata, ma risolve un sacco di dubbi. Ora, avviando l'esempio con il &lt;em&gt;profiler&lt;/em&gt; avviato, vedo che viene eseguita una sola query per recuperare l'&lt;em&gt;entity&lt;/em&gt; del colore...&lt;/p&gt; &lt;p&gt;Ma il &lt;em&gt;TryGetObjectByKey&lt;/em&gt; non solo &amp;#232; in grado di prendere il valore se &amp;#232; gi&amp;#224; stata trattata, ma esegue lui stesso una query nel caso il valore non fosse presente. Il codice qui sopra potrebbe essere scritto in modo pi&amp;#249; semplice:&lt;/p&gt; &lt;p&gt;&lt;em&gt;using (TestModel.TestEntities context = new TestModel.TestEntities()) &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int colore = 2; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var a = new TestModel.Articles(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Article = &amp;quot;Art3 &amp;quot; + DateTime.Now.ToString(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TestModel.Colors c; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; object obj = null; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.TryGetObjectByKey( &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new System.Data.EntityKey( &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string.Format(&amp;quot;{0}.{1}&amp;quot;, context.DefaultContainerName, &amp;quot;Colors&amp;quot;), &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Id&amp;quot;, &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; colore), out obj); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; c = (TestModel.Colors)obj; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Colors = c; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.AddToArticles(a); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a = new TestModel.Articles(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Article = &amp;quot;Art4 &amp;quot; + DateTime.Now.ToString(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; obj = null; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.TryGetObjectByKey( &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new System.Data.EntityKey( &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string.Format(&amp;quot;{0}.{1}&amp;quot;, context.DefaultContainerName, &amp;quot;Colors&amp;quot;), &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Id&amp;quot;, &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; colore), out obj); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; c = (TestModel.Colors)obj; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Colors = c; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.AddToArticles(a); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.SaveChanges(); &lt;br /&gt;}&lt;/em&gt;&lt;/p&gt; &lt;p&gt;(*) Il codice non viene mai eseguito.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2367/Fatto-Pace-Entity-Framework-Minimo-Cache.aspx"/><issued>2008-08-22T14:26:34+00:00</issued><modified>2008-08-22T14:26:34+00:00</modified><slash:comments>2</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2367/Fatto-Pace-Entity-Framework-Minimo-Cache.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2367.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2367</trackback:ping></entry><entry><title>Entity framework... un minimo di cache faceva schifo?</title><id>http://blogs.aspitalia.com/az/post2366/Entity-Framework.-Minimo-Cache-Faceva-Schifo.aspx</id><created>2008-08-21T16:50:05+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2366' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Leggero. Continuano dei test a tempo perso con l'entity framework. Siccome volevo legare delle propriet&amp;#224; ad una tabella per vedere il comportamento dell'EF (lo chiamo cos&amp;#236; amichevolmente perch&amp;#233; inizio ad avere confidenza con questa tecnologia), ho creato una struttura simile a questa:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;361&quot; alt=&quot;diagramma tabelle&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/entityframew.unminimodicachefacevaschifo_10861/image_3.png&quot; width=&quot;405&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;L'entity framework crea il tutto in modo corretto:&lt;/p&gt; &lt;p&gt;&lt;img height=&quot;212&quot; alt=&quot;ado entity&quot; src=&quot;http://blogs.aspitalia.com/img/andrewz/entityframew.unminimodicachefacevaschifo_10861/image_6.png&quot; width=&quot;449&quot; border=&quot;0&quot; /&gt; &lt;/p&gt; &lt;p&gt;Nella tabella colors sono presenti dei record cos&amp;#236; composta:&lt;/p&gt; &lt;table cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;400&quot; border=&quot;0&quot;&gt;&lt;tbody&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;Id&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;Color&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;1&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;Black&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;2&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;White&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td  width=&quot;200&quot;&gt;3&lt;/td&gt; &lt;td  width=&quot;200&quot;&gt;Red&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Per inserire in &lt;em&gt;Articles&lt;/em&gt; nuovi record con un colore corrispondente, mi basta scrivere il codice:&lt;/p&gt; &lt;p&gt;&lt;em&gt;using (TestModel.TestEntities context = new TestModel.TestEntities()) &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var a = new TestModel.Articles(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Article = &amp;quot;Art &amp;quot; + DateTime.Now.ToString(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var c = context.Colors.Where(w =&amp;gt; w.Color == &amp;quot;White&amp;quot;).First(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a.Colors = c; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.SaveChanges(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Tutto funziona bene. Con il profiler vedo che esegue una prima query per sapere l'&lt;em&gt;id&lt;/em&gt; del colore che sar&amp;#224; poi utilizzato per l'inserimento nella tabella &lt;em&gt;Articoles&lt;/em&gt;. A chiunque sarebbe venuto lo stesso sospetto che &amp;#232; venuto a me: nel caso caso di inserimento di pi&amp;#249; oggetti &lt;em&gt;Articles&lt;/em&gt;, avendo richiedendo lo stesso colore, come si comporta l'EF?&lt;/p&gt; &lt;p&gt;Ipotizzando questo codice:&lt;/p&gt; &lt;p&gt;&lt;em&gt;using (TestModel.TestEntities context = new TestModel.TestEntities()) &lt;br /&gt;{ &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; string colore = &amp;quot;White&amp;quot;; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var a = new TestModel.Articles(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; a.Article = &amp;quot;Art &amp;quot; + DateTime.Now.ToString(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var c = context.Colors.Where(w =&amp;gt; w.Color == colore).First(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; a.Colors = c; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.SaveChanges(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; a = new TestModel.Articles(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; a.Article = &amp;quot;Art2 &amp;quot; + DateTime.Now.ToString(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; c = context.Colors.Where(w =&amp;gt; w.Color == colore).First(); &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; a.Colors = c; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; context.SaveChanges(); &lt;br /&gt;}&lt;/em&gt; &lt;/p&gt; &lt;p&gt;E' per due volte richiesto il colore &lt;em&gt;bianco&lt;/em&gt;. Avvio il codice, il tutto &amp;#232; inserito correttamente. Guardo con il &lt;em&gt;profiler&lt;/em&gt;... delusione: esegue per ben due volte la query per ottenere l'&lt;em&gt;id&lt;/em&gt; del colore. Una possibile soluzione? Crearsi una logica interna di cache... ok, ma un minimo di cache delle entit&amp;#224; l'avrei gradita.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2366/Entity-Framework.-Minimo-Cache-Faceva-Schifo.aspx"/><issued>2008-08-21T18:50:05+00:00</issued><modified>2008-08-21T18:50:05+00:00</modified><slash:comments>4</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2366/Entity-Framework.-Minimo-Cache-Faceva-Schifo.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2366.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2366</trackback:ping></entry><entry><title>Entity Framework e il namespace EntityClient</title><id>http://blogs.aspitalia.com/az/post2363/Entity-Framework-Namespace-EntityClient.aspx</id><created>2008-08-16T14:01:17+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2363' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Sabato pomeriggio. L'entity framework permette, grazie alle classi contenuti nel namespace &lt;em&gt;EntityClient&lt;/em&gt;, la connessione e l'esecuzione di query direttamente sulle &lt;em&gt;entity&lt;/em&gt;, come se si trattasse di un database. Riferendomi sempre a grandi linee agli esempi esposti &lt;a href=&quot;http://blogs.aspitalia.com/az/post2359/lentity-framework-framework-3.5-sp.aspx&quot;&gt;qui&lt;/a&gt; e &lt;a href=&quot;http://blogs.aspitalia.com/az/post2361/entity-framework-sql-generato.aspx&quot;&gt;qui&lt;/a&gt;, ecco un banale esempio di utilizzo delle classi di questo namespace:&lt;/p&gt; &lt;p&gt;&lt;em&gt;using (System.Data.EntityClient.EntityConnection conn = new System.Data.EntityClient.EntityConnection(&quot;name=TestEntitiesCode&quot;))&lt;br /&gt; {&lt;br /&gt; conn.Open(); &lt;/em&gt; &lt;p&gt;&lt;em&gt; System.Data.EntityClient.EntityCommand comm= conn.CreateCommand();&lt;br /&gt; comm.CommandText = &quot;select na.Id, na.Names1, na.Books from TestEntitiesCode.Names as na&quot;;&lt;br /&gt; System.Data.EntityClient.EntityDataReader re = comm.ExecuteReader(System.Data.CommandBehavior.SequentialAccess);&lt;br /&gt; while (re.Read())&lt;br /&gt; {&lt;br /&gt; Response.Write(string.Format(&quot;{0}, {1} = &quot;,&lt;br /&gt; re[&quot;Id&quot;], re[&quot;Names1&quot;]));&lt;br /&gt; ShowChildren(re[&quot;Books&quot;] as System.Data.Common.DbDataReader);&lt;br /&gt; Response.Write(&quot;&amp;lt;br /&amp;gt;&quot;);&lt;br /&gt; }&lt;br /&gt; re.Close();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;private void ShowChildren(System.Data.Common.DbDataReader children)&lt;br /&gt;{&lt;br /&gt; while (children.Read())&lt;br /&gt; {&lt;br /&gt; Response.Write(&quot;[[&quot;);&lt;br /&gt; System.Data.IExtendedDataRecord columns = children as System.Data.IExtendedDataRecord;&lt;br /&gt; for (int i = 0; i &amp;lt; columns.FieldCount; i++)&lt;br /&gt; Response.Write(columns[i].ToString() + &quot;, &quot;);&lt;br /&gt; Response.Write(&quot;]]&quot;);&lt;br /&gt; }&lt;br /&gt;} &lt;/em&gt; &lt;p&gt;Due parole sulla sintassi. In &lt;em&gt;EntityConnection&lt;/em&gt; dobbiamo specificare il nome della classe del nostro model creato con VS2008 (nel dettaglio, aperto il model in VS2008 &#232; sufficiente leggere la propriet&#224; &quot;Entity Container&quot; nelle properties. Nell'esempio viene usata il &lt;em&gt;datareader&lt;/em&gt;. Per le propriet&#224; dirette come l'&lt;em&gt;id&lt;/em&gt; e il name dell'entit&#224; &lt;em&gt;Names&lt;/em&gt;, possiamo accedere direttamente con il nome stesso, ma in caso volessimo accedere, come nell'esempio, a una collection di entity come la lista dalla tabella &lt;em&gt;Books&lt;/em&gt;, dobbiamo complicare un po' le cose. L'oggetto presente in &lt;em&gt;re[&quot;Books&quot;]&lt;/em&gt; &#232; &lt;em&gt;System.Data.Query.ResultAssembly.BridgeDataReader&lt;/em&gt; ma possiamo passarlo come un DbDataReader come nell'esempio. &lt;p&gt;In ShowChildren possiamo anche andare oltre, leggendo il tipo per ogni column e agire di conseguenza. Ma non ho approfondito oltre ed &#232; sabato anche per me. Comunque, il risultato del codice &#232; il seguente: &lt;p&gt;&lt;em&gt;1, Andrea = [[1, Book 1, ]]&lt;br /&gt;2, Andrea2 = [[2, Book 2, ]][[3, Book 3, ]]&lt;br /&gt;3, Andrea3 = [[4, Book 2, ]][[5, Book 3, ]]&lt;/em&gt; &lt;p&gt;Andando a vedere con il Profiler se ci fossero ancora sorprese, troviamo la query gi&#224; spiegata &lt;a href=&quot;http://blogs.aspitalia.com/az/post2361/entity-framework-sql-generato.aspx&quot;&gt;precedentemente&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/az/post2363/Entity-Framework-Namespace-EntityClient.aspx"/><issued>2008-08-16T16:01:17+00:00</issued><modified>2008-08-16T16:01:17+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/az/post2363/Entity-Framework-Namespace-EntityClient.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/az/CommentRSS2363.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2363</trackback:ping></entry></feed>