.Net Framework 4.0 http://blogs.ugidotnet.org/PietroLibroBlog/category/.Net Framework 4.0.aspx .Net Framework 4.0 it-IT Pietro Libro pietro.libro@libero.it Subtext Version 2.6.0.0 Dynamic Data Provider per EF6 released http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/03/03/dynamic-data-provider-per-ef6-released.aspx <p>Sono stati rilasciati in RTM, <em>ASP.NET Dynamic Data</em> e <em>EntityDataSource</em> per EntityFrameowrk 6. Per provare la nuova versione di <em>Dynamic Data</em> è sufficiente creare un nuovo progetto di tipo “ASP.NET Dynamic Data Entities Web Application”, ed installare tramite NuGet il package <em>Microsoft.AspNet.DynamicData.EFProvider</em>:</p> <p align="center"><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/3b52774302cc_7140/image_2.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/3b52774302cc_7140/image_thumb.png" width="244" height="33" /></a></p> <p>Eventualmente forziamo la scrittura dei <em>Template</em> (“A” per sovrascrivere tutto):</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/3b52774302cc_7140/image_4.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; border-left: 0px; display: block; padding-right: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/3b52774302cc_7140/image_thumb_1.png" width="244" height="39" /></a></p> <p>Aggiungiamo in modalità <em>Code First</em> una semplice classe <em>Book </em>e relativo <em>DbContext</em>:</p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> Book { <span class="kwrd">public</span> <span class="kwrd">int</span> Id { get; set; } <span class="kwrd">public</span> <span class="kwrd">string</span> Title { get; set; } <span class="kwrd">public</span> <span class="kwrd">string</span> Authors { get; set; } <span class="kwrd">public</span> <span class="kwrd">int</span> Pages { get; set; } } <span class="kwrd">public</span> <span class="kwrd">class</span> Db : DbContext { <span class="kwrd">public</span> DbSet&lt;Book&gt; Books { get; set; } <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnModelCreating(DbModelBuilder modelBuilder) { <span class="kwrd">base</span>.OnModelCreating(modelBuilder); } }</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p> </p> <p>Nel <em>Global.asax</em> registriamo il nostro <em>DbContext</em>:</p> <pre class="csharpcode">DefaultModel.RegisterContext( <span class="kwrd">new</span> Microsoft.AspNet.DynamicData.ModelProviders.EFDataModelProvider(() =&gt; <span class="kwrd">new</span> Db()), <span class="kwrd">new</span> ContextConfiguration { ScaffoldAllTables = <span class="kwrd">true</span> });</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p> </p> <p>F5, per vedere in azione il nostro <em>Data Site</em>:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/3b52774302cc_7140/image_6.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/3b52774302cc_7140/image_thumb_2.png" width="244" height="156" /></a></p> <p>Discorso simile per l’utilizzo <em>dell’EntityDataSource</em> control.</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101806.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/03/03/dynamic-data-provider-per-ef6-released.aspx Mon, 03 Mar 2014 10:06:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/03/03/dynamic-data-provider-per-ef6-released.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101806.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101806.aspx ASP.NET Dynamic Data provider (preview) per EF6 http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/01/31/asp.net-dynamic-data-provider-preview-per-ef6.aspx <p>Rilasciato un aggiornamento per <em>ASP.NET DynamicData</em> e <em>DataSourceControl</em> per Entity Framework 6. Tutti i dettagli del caso sul <a href="http://blogs.msdn.com/b/webdev/archive/2014/01/30/announcing-preview-of-dynamic-data-provider-and-entitydatasource-control-for-entity-framework-6.aspx" target="_blank">blog originale</a>.</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101763.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/01/31/asp.net-dynamic-data-provider-preview-per-ef6.aspx Fri, 31 Jan 2014 10:23:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/01/31/asp.net-dynamic-data-provider-preview-per-ef6.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101763.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101763.aspx Request Batching in Web Api 2 http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/12/23/request-batching-in-web-api-2.aspx <p>Una funzionalità molto interessante introdotta con ASP.NET Web API 2 OData è il supporto “Batching”, ovvero la possibilità di “impacchettare” in una singola richiesta HTTP piu’ richieste Web API (<em>action</em>) e ricevere in un’unica risposta HTTP i risultati ottenuti dalle singole invocazioni delle Web API. Questa funzionalità è molto interessante in quanto ci permette di minimizzare il numero di richieste\risposte tra client e server, riducendo il traffico di rete (pensiamo al Cloud…).  </p> <p>Per abilitare <em>Server Side</em> questa funzionalità è necessario esporre tramite registrazione, un <em>HTTP batch endpoint</em> utilizzando il metodo <em>MapHttpBatchRoute</em> esposto dall’instanza <em>Routes</em> della classe <em>HttpRouteCollection</em>:</p><pre class="csharpcode">config.Routes.MapHttpBatchRoute( routeName: <span class="str">"BatchApi"</span>, routeTemplate: <span class="str">"api/batch"</span>, batchHandler: <span class="kwrd">new</span> System.Web.Http.Batch.DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer));</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p> </p> <p>Il codice del Controller Web Api è relativamente semplice (è in allegato) ed è stato utilizzato come DEMO per la mia sessione durante l’ultimo l’evento organizzato da <a href="http://www.domusdotnet.org/" target="_blank">DomusDotNet</a>. A questo punto la palla passa <em>Client Side</em>, dove tramite un’unica chiamata HTTP vogliamo ottenere l’elenco di tutte le entità <em>Car</em> serializzate, l’inserimento di una nuova entità <em>Car</em> e la modifica del valore di una proprietà di un’entità precedentemente recuperata.</p> <p>Iniziamo con il recuperare l’entità <em>Car</em> con Id=1</p><pre class="csharpcode">HttpClient client = <span class="kwrd">new</span> HttpClient(); <span class="kwrd">string</span> response = await client.GetStringAsync(<span class="str">"http://localhost:31613/Api/Cars/1"</span>); Car car = (Newtonsoft.Json.JsonConvert.DeserializeObject(response) <span class="kwrd">as</span> Newtonsoft.Json.Linq.JObject).ToObject&lt;Car&gt;();</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p> </p> <p>Poi un <em>HttpRequestMessage</em> per ottenere (GET) l’elenco di tutte le entità:</p><pre class="csharpcode">HttpRequestMessage getCars = <span class="kwrd">new</span> HttpRequestMessage(HttpMethod.Get, <span class="str"><a href="http://localhost:31613/Api/Cars">http://localhost:31613/Api/Cars</a></span>);</pre><pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Un altro <em>HttpRequestMessage</em> per aggiungere (POST) una nuova entità:</p><pre class="csharpcode">JsonMediaTypeFormatter formatter = <span class="kwrd">new</span> JsonMediaTypeFormatter(); HttpRequestMessage postCar = <span class="kwrd">new</span> HttpRequestMessage(HttpMethod.Post, <span class="str">"http://localhost:31613/Api/Cars"</span>); postCar.Content = <span class="kwrd">new</span> ObjectContent&lt;Car&gt;(<span class="kwrd">new</span> Car() { Brand_Id = 1, DailyRent = 50.0f, EngineSize = <span class="str">"2500"</span>, Model = <span class="str">"GTV"</span>, Note = <span class="str">"---"</span> },formatter);</pre><pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Ed infine un <em>HttpRequestMessage</em> per aggiornare (PUT) l’entità <em>Car</em> precedentemente recuperata:</p><pre class="csharpcode">car.Note += <span class="str">" BATCH"</span>; HttpRequestMessage putCar = <span class="kwrd">new</span> HttpRequestMessage(HttpMethod.Put, <span class="kwrd">string</span>.Format(<span class="str">"http://localhost:31613/Api/Cars?id={0}"</span>, car.Id)); putCar.Content = <span class="kwrd">new</span> ObjectContent&lt;dynamic&gt;(car, formatter);</pre><pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>a questo punto, dobbiamo “impacchettare” le singole richieste in un’unica richiesta HTTP, utilizzanto un’istanza di <em>MultiPartContent</em>:</p><pre class="csharpcode">HttpMessageContent getCarsContent = <span class="kwrd">new</span> HttpMessageContent(getCars); HttpMessageContent postCarContent = <span class="kwrd">new</span> HttpMessageContent(postCar); HttpMessageContent putCarContent = <span class="kwrd">new</span> HttpMessageContent(putCar); MultipartContent multiPartContent = <span class="kwrd">new</span> MultipartContent(<span class="str">"mixed"</span>, <span class="str">"batch_"</span> + Guid.NewGuid().ToString()); multiPartContent.Add(getCarsContent); multiPartContent.Add(postCarContent); multiPartContent.Add(putCarContent); HttpRequestMessage batchRequest = <span class="kwrd">new</span> HttpRequestMessage(HttpMethod.Post, <span class="str">"http://localhost:31613/api/batch"</span>); batchRequest.Content = multiPartContent;</pre><pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Non ci resta che effettuare la richiesta al <em>Server</em>:</p><pre class="csharpcode">HttpResponseMessage multipartResponse = await client.SendAsync(batchRequest); MultipartMemoryStreamProvider responseContents = await multipartResponse.Content.ReadAsMultipartAsync();</pre><pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>e recuperare le singole risposte:</p><pre class="csharpcode"><span class="rem">////Status Code: 200, Ok.</span> HttpResponseMessage getResponse = await responseContents.Contents[0].ReadAsHttpResponseMessageAsync(); <span class="rem">////Status Code: 201, Created.</span> HttpResponseMessage postResponse = await responseContents.Contents[1].ReadAsHttpResponseMessageAsync(); <span class="rem">////Status Code:204, Not Content.</span> HttpResponseMessage putResponse = await responseContents.Contents[2].ReadAsHttpResponseMessageAsync();</pre> <p> </p> <p>Normalmente le singole richieste contenute all’interno di un “batch” sono eseguite sequenzialmente, di conseguenza in questo caso, la richiesta di POST partirebbe subito dopo quella di GET ed immediatamente prima di quella di PUT. Se l’ordine di esecuzione non è importante, possiamo eseguire le richieste in modo asincrono impostando la proprietà <em>ExecutionOrder </em>a <em>BatchExecutionOrder.NonSequential:</em></p><pre class="csharpcode">config.Routes.MapHttpBatchRoute( routeName: <span class="str">"BatchApi"</span>, routeTemplate: <span class="str">"api/batch"</span>, batchHandler: <span class="kwrd">new</span> System.Web.Http.Batch.DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer) { ExecutionOrder = System.Web.Http.Batch.BatchExecutionOrder.NonSequential });</pre><pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <div id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:7b2b768f-9337-4757-86e0-c75f6442084c" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"><p>Attach <a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Batch-Requestes-in-Web-Api-2_86F2/CarsController.cs" target="_blank">Cars Controller Code</a></p></div><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101749.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/12/23/request-batching-in-web-api-2.aspx Mon, 23 Dec 2013 12:49:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/12/23/request-batching-in-web-api-2.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101749.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101749.aspx EF : Relazione one-to-many Table-View http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/12/19/ef-relazione-one-to-many-table-view.aspx <p>Immaginiamo di avere un database SQL Server esistente, e vogliamo utilizzare Entity Framework Code First per mappare il modello dati. </p> <p>Supponendo di avere due tabelle “Items” e “Categories” in relazione come da <em>Database Diagram</em> seguente:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/a8bf8935c20d_D16A/image_2.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/a8bf8935c20d_D16A/image_thumb.png" width="244" height="94" /></a></p> <p>Ed una “Vista” SQL Server definita come segue:</p> <pre class="csharpcode"><span class="kwrd">CREATE</span> <span class="kwrd">VIEW</span> [dbo].[VCategories] <span class="kwrd">AS</span> <span class="kwrd">SELECT</span> Id, Name <span class="kwrd">FROM</span> Categories <span class="kwrd">WHERE</span> (Deleted = 0)</pre> <pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Aggiungiamo due classi C# definite in questo modo:</p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> Category { <span class="kwrd">public</span> <span class="kwrd">int</span> Id { get; set; } <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; } }</pre> <p> </p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> Item { <span class="kwrd">public</span> <span class="kwrd">int</span> Id { get; set; } <span class="kwrd">public</span> <span class="kwrd">string</span> Code { get; set; } <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; } <span class="kwrd">public</span> <span class="kwrd">int</span> CategoryId { get; set; } <span class="kwrd">public</span> Category Category { get; set; } }</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p> </p> <p>che mappiamo tramite <em>OnModelCreating (</em>nella classe derivata da <em>DbContext) </em>come segue :</p> <pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity&lt;Category&gt;().ToTable(<span class="str">"VCategories"</span>) .Property(c =&gt; c.Description).HasColumnName(<span class="str">"Name"</span>); modelBuilder.Entity&lt;Item&gt;().ToTable(<span class="str">"Items"</span>); modelBuilder.Entity&lt;Item&gt;().HasRequired(x =&gt; x.Category) .WithMany().HasForeignKey(o =&gt; o.CategoryId); }</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p> </p> <p>Per verificare il funzionamento del <em>mapping</em> possiamo scrivere del codice tipo:</p> <pre class="csharpcode">Item item = <span class="kwrd">null</span>; <span class="kwrd">using</span> (Db db = <span class="kwrd">new</span> Db()) { Console.WriteLine(<span class="str">"Items count : {0}"</span>, db.Items.Count()); Category category = (from c <span class="kwrd">in</span> db.Categories <span class="kwrd">where</span> c.Id == 1 select c) .FirstOrDefault(); item = <span class="kwrd">new</span> Item() { Category = category, CategoryId = category.Id, Code = <span class="str">"Code #1"</span>, Description = <span class="str">"Description #1"</span>, }; db.Items.Add(item); db.SaveChanges(); Console.WriteLine(<span class="str">"Items count : {0}"</span>, db.Items.Count()); } <span class="kwrd">using</span> (Db db = <span class="kwrd">new</span> Db()) { <span class="rem">////Edit</span> item.Description = <span class="str">"New Description #1."</span>; db.Entry&lt;Item&gt;(item).State = System.Data.Entity.EntityState.Modified; db.SaveChanges(); Console.WriteLine(<span class="str">"Items count : {0}"</span>, db.Items.Count()); } <span class="kwrd">using</span> (Db db = <span class="kwrd">new</span> Db()) { <span class="rem">////Delete. </span> db.Entry&lt;Item&gt;(item).State = System.Data.Entity.EntityState.Deleted; db.SaveChanges(); Console.WriteLine(<span class="str">"Items count : {0}"</span>, db.Items.Count()); }</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101747.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/12/19/ef-relazione-one-to-many-table-view.aspx Thu, 19 Dec 2013 16:55:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/12/19/ef-relazione-one-to-many-table-view.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101747.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101747.aspx Web Api e Debug su Azure http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/11/19/web-api-e-debug-su-azure.aspx <p>Se abbiamo la necessità di debuggare le nostre Web Api pubblicate su Azure, i passi da seguire sono veramente pochi e semplici:</p> <ol> <li>Download ed installazione di Azure SDK 2.2 </li> <li>Aprire la <em>Solution </em>contenente<em> </em>il progetto Web con la definizione delle Web API </li> <li>Connettersi a <em>Windows Azure</em> tramite l’apposito link in <em>Server Explorer</em>: <br /> <br /> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_2.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_thumb.png" width="244" height="156" /></a></p> </li> <li>Pubblicare il progetto (in Debug): <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_8.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_thumb_3.png" width="244" height="92" /></a> </p> <br /> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_4.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_thumb_1.png" width="244" height="105" /></a></p> <br /></li> <li>Utilizzare la funzione <i>Attach debugger</i> per il <em>Web Site</em> oggetto del <em>Debug</em>: <p> <a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_10.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_thumb_4.png" width="244" height="193" /></a> <br /></p> </li> <li>Si apre una nuova finestra del Browser con il <em>Web Site</em> </li> <li>Aggiungiamo dove necessario i <em>breakpoint</em> nel codice (ad esempio su un’azione di GET del nostro <em>Controller</em>) </li> <li>Invochiamo l’URL e per “magia” (la prima volta puo’ impiegare qualche di tempo) ci troviamo a debuggare la nostra applicazione appena pubblicata: <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_12.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_thumb_5.png" width="244" height="72" /></a></p> </li> </ol> <p>N.B: I passi precedenti si riferiscono all’utilizzo di VS 2013, per VS 2012 bisogna abilitare il <em>remote debugging</em> tramite il portale della nostra sottoscrizione Azure</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_14.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Web-Api-Debug-su-Azure_783C/image_thumb_6.png" width="244" height="126" /></a></p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101726.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/11/19/web-api-e-debug-su-azure.aspx Tue, 19 Nov 2013 10:40:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/11/19/web-api-e-debug-su-azure.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101726.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101726.aspx EF6 RTM Available http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/10/17/ef6-rtm-available.aspx <p>Con il rilascio di VS 2013, puntuale anche il rilascio in RTM di Entity Framework 6, tutti i dettagli direttamente sul blog di <a href="http://blogs.msdn.com/b/adonet/archive/2013/10/17/ef6-rtm-available.aspx#!" target="_blank">ADO.NET</a>.</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101699.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/10/17/ef6-rtm-available.aspx Thu, 17 Oct 2013 16:25:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/10/17/ef6-rtm-available.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101699.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101699.aspx EF 6 : Logging &amp; Interception http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/09/04/ef-6-logging-amp-interception.aspx <p> </p> <p>Una delle nuove feature introdotte nella versione 6 di Entity Framework (attualmente in RC) è il supporto al <em>logging</em> dell’SQL generato dal runtime di EF6. A tal fine è sufficiente passare un opportuno <em>delegate</em> alla proporietà <em>Log</em> esposta da <em>DbContext.Database</em>. Per gli esempi riprendiamo lo scenario del <a href="http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/19/ef6-beta-multiple-contexts-per-database-multi-tenant-migrations.aspx" target="_blank">post precedente</a>. </p> <p>Supponiamo di avere il seguente codice:</p> <pre class="csharpcode"> <span class="kwrd">using</span> (CarContext db = <span class="kwrd">new</span> CarContext()) { System.Console.WriteLine(<span class="str">"Cars in database : {0}"</span>, db.Cars.Count()); <span class="rem">////Add a new car.</span> Car car = <span class="kwrd">new</span> Car() { Brand = <span class="str">"Alfa Romeo"</span>, Model = <span class="str">"Giulietta"</span> }; db.Cars.Add(car); db.SaveChanges(); System.Console.WriteLine(<span class="str">"Cars in database : {0}"</span>, db.Cars.Count()); }</pre> <p /><style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Che banalmente visualizza il numero di auto (Cars) presenti nel  <em>repository</em>, ne aggiunge una e riesegue la conta delle auto registrate. Se volessimo analizzare l’SQL generato un ottimo strumento è sicuramete il SQL Profiler di SQL Server (che non dovrebbe mai mancare quando si lavora con un ORM <img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Smile" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/EF-6--Logging--Interceptor_6F20/wlEmoticon-smile_2.png" /> ), ma se utilizziamo EF6, ed il nostro obiettivo è semplicemente “scoprire\loggare” l’SQL generato da EF, possiamo modificare il codice precedente aggiungendo dopo la definizione del <em>DbContext,</em> la riga seguente:</p> <pre class="csharpcode"> db.Database.Log = Console.Write;</pre> <pre class="csharpcode"> </pre> <p>Dove la proprietà <em>Log</em> è cosi’ definita:</p> <pre class="csharpcode"><span class="kwrd">public</span> Action&lt;<span class="kwrd">string</span>&gt; Log { get; set; }</pre> <pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Eseguendo il codice della nostra applicazione dovremmo ottenere una “Console” simile alla seguente:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/EF-6--Logging--Interceptor_6F20/image_2.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/EF-6--Logging--Interceptor_6F20/image_thumb.png" width="244" height="172" /></a></p> <p>Di default il log è molto chiaro in quanto ci restituisce il testo SQL del comando, quando è stato eseguito, il tempo impiegato, il tipo di risultato, gli eventuali parametri ed il tipo corrispondente. Possiamo ovviamente cambiare il contenuto e la formattazione del log secondo le nostre esigenze (e non solo) come vedremo piu’ avanti. Per come è definita la proprietà <em>Log</em>, qualsiasi funzione che accetta una stringa puo’ essere utilizzata per scrivere il nostro log. Quindi potremmo utilizzare un metodo tipo il seguente:</p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Log(<span class="kwrd">string</span> sql) { Console.WriteLine(<span class="str">"------------------------------------"</span>); Console.WriteLine(<span class="str">"SQL LOG: {0} "</span>, sql); Console.WriteLine(<span class="str">"------------------------------------"</span>); }</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p> </p> <p>oppure:</p> <pre class="csharpcode">System.IO.StreamWriter streamWriter = <span class="kwrd">new</span> System.IO.StreamWriter (fileStream, System.Text.ASCIIEncoding.ASCII ); db.Database.Log = sql =&gt; streamWriter.Write(sql);</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p> </p> <p>Per scrivere il log direttamente su file. Il concetto dovrebbe essere abbastanza chiaro. Vediamo come personalizzare la formattazione del log. </p> <p><em>Database.Log</em> non fa altro che utilizzare un ogetto <em>DatabaseLogFormatter </em>che a sua volta implementa le interfacce <em>IDbCommandInterceptor</em> e <em>IDbInterceptor </em>che sono rispettivamente l’interfaccia che permette di registrare un oggetto che possa ricevere notifiche da parte di Entity Framework quando un comando viene eseguito e l’interfaccia base per tutte le interfacce che permettono di fornire un <em>Interception Point</em> per differenti tipi di operazione.</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/EF-6--Logging--Interceptor_6F20/image_4.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/EF-6--Logging--Interceptor_6F20/image_thumb_1.png" width="134" height="244" /></a></p> <p>Quindi, per creare il nostro “Formattatore Custom” non ci resta che ereditare dalla classe <em>DatabaseLogFormatter</em> ed eseguire <em>l’override</em> dei metodi che ci interessano, come nel caso seguente:</p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> CustomLogFormatter : DatabaseLogFormatter { <span class="kwrd">public</span> CustomLogFormatter(DbContext context, Action&lt;<span class="kwrd">string</span>&gt; writeAction) : <span class="kwrd">base</span>(context, writeAction) { } <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> LogCommand&lt;TResult&gt;( DbCommand command, DbCommandInterceptionContext&lt;TResult&gt; interceptionContext) { Write(<span class="kwrd">string</span>.Format(<span class="str">"{0}{1}"</span>, <span class="str">"==============================================="</span>, Environment.NewLine)); Write(<span class="kwrd">string</span>.Format( <span class="str">"Context{2}{0}{2}Command{2}{1}{2}"</span>, Context.GetType().Name, command.CommandText.Replace(Environment.NewLine, <span class="str">""</span>), Environment.NewLine)); Write(<span class="kwrd">string</span>.Format(<span class="str">"{0}{1}"</span>, <span class="str">"==============================================="</span>, Environment.NewLine)); } }</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p> </p> <p>Dove, l’<em>override</em> del metodo <em>LogCommand </em>esegue la formattazione del comando prima che questo sia eseguito da Entity Framework<em>. LogCommand</em> a sua volta  chiama eventualmente il metodo <em>LogParameter</em> per ogni parametro del comando, è necessario eseguire l’override di <em>LogParameter </em>per “customizzare” la formattazione del log dei paramateri. Infine, se vogliamo cambiare la formattazione del risultato, è necessario effettuare l’override di <em>LogResult. </em>Per interrompere l’esecuzione del comando, possiamo utilizzare il metodo :</p> <pre class="csharpcode">interceptionContext.SuppressExecution()</pre> <pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Nel corpo dell’<em>override</em> di <em>LogCommand. </em>Per vedere in “funzione” il nostro “Formatter” è sufficiente registrare l’istanza di <em>CustomLogFormatter</em> tramite una classe derivata da <em>DbConfiguration</em> presente nello stesso assembly che contiene la definizione del <em>DbContext:</em></p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> MyDbConfiguration : DbConfiguration { <span class="kwrd">public</span> MyDbConfiguration() { SetDatabaseLogFormatter( (context, writeAction) =&gt; <span class="kwrd">new</span> CustomLogFormatter(context, writeAction)); } }</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Eseguendo, otteniamo il “nostro” log:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/EF-6--Logging--Interceptor_6F20/image_6.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/EF-6--Logging--Interceptor_6F20/image_thumb_2.png" width="244" height="118" /></a></p> <p>Per approfondimenti:</p> <p><a title="https://entityframework.codeplex.com/wikipage?title=Interception" href="https://entityframework.codeplex.com/wikipage?title=Interception" target="_blank">Entity Framework Codeplex</a></p> <p><a href="http://blog.oneunicorn.com/2013/05/08/ef6-sql-logging-part-1-simple-logging/" target="_blank">One Unicorn: EF6 SQL Logging</a></p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101658.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/09/04/ef-6-logging-amp-interception.aspx Wed, 04 Sep 2013 15:15:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/09/04/ef-6-logging-amp-interception.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101658.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101658.aspx Disponibile EF 6 RC http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/22/disponibile-ef-6-rc.aspx <p>Rilasciata la RC di Entity Framework 6, tutti i dettagli e le novità rispetto alla Beta 1, <a href="http://blogs.msdn.com/b/adonet/archive/2013/08/21/ef6-release-candidate-available.aspx" target="_blank">qui</a>. </p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101644.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/22/disponibile-ef-6-rc.aspx Thu, 22 Aug 2013 09:25:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/22/disponibile-ef-6-rc.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101644.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101644.aspx EF6 (beta) : Multiple Contexts per Database, Multi-Tenant Migrations http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/19/ef6-beta-multiple-contexts-per-database-multi-tenant-migrations.aspx <p>Una delle novità introdotte con EF6 è la possibilità di gestire molteplici modelli per singola istanza di database, che non vuol dire usare lo stesso contesto piu’ volte nello stesso database, ma poter utilizzare Entity Framework Migrations e relativa Migration History Table per gestire la migrazione di due o piu’ modelli per singolo database fisico. Specifichiamo questa <em>feature</em> come <em>Multi-Tenant Migrations</em>.</p> <p>Come esempio, supponiamo di avere due classi <em>Bus</em> e <em>Car</em> facenti parte dello stesso <em>Domain</em> di una nostra applicazione, ma interessate da due <em>DbContext </em>diversi, rispettivamente <em>BusContext</em> e <em>CarContext</em>, come da <em>Class Diagram</em> seguente:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_16.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; border-left: 0px; display: block; padding-right: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_thumb.png" width="244" height="62" /></a></p> <p>Provando ad abilitare EF Migrations per il progetto corrente, essendo presenti due <em>DbContext</em>, il “Package Manager Console” risponderebbe restituendo l’errore seguente:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_4.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_thumb_1.png" width="244" height="72" /></a></p> <p>Vediamo come utilizzare <em>Multi-Tenant Migrations</em>: iniziamo ad utilizzare la prima delle novità di EF6 (migrations), l’opzione “-MigrationDirectory” che ci permette di specificare, insieme all’opzione “-ContextTypeName” che rispettivamente indicano dove far risiedere i piani di migrazione e quale <em>DbContext</em> considerare. Il comando completo da utilizzare diventa quindi:</p> <p><em>PM&gt;Enable-Migrations -MigrationsDirectory BusDbContextMigration -ContextTypeName MultiTenantMigration.BusContext</em></p> <p>Questa volta tutto fila liscio, ottenendo un messaggio di questo tipo:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_6.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_thumb_2.png" width="244" height="39" /></a></p> <p>Il “Solution Explorer” dovrebbe apparire simile alla figura seguente:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_8.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_thumb_3.png" width="244" height="175" /></a></p> <p>Visualizziamo il codice della classe <em>Configuration.cs</em> e modifichiamolo opportunatamente impostando la proprietà <em>ContextKey</em> che altro non è una nuova proprietà di configurazione per EF6 Migrations che aggiunge nella “_MigrationHistory Table” una nuova colonna che rende possibile la funzionalità “Multi-Tenant”:</p><pre class="csharpcode"><span class="kwrd">public</span> Configuration() { ContextKey = <span class="str">"BusContextKey"</span>; AutomaticMigrationsEnabled = <span class="kwrd">false</span>; MigrationsDirectory = <span class="str">@"BusDbContextMigration"</span>; }</pre><pre class="csharpcode"> </pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Come prima, eseguiamo le operazioni precedenti per abilitare la migrazione anche per il <em>DbContext </em>“CarContext” ottenendo un “Solution Explorer” simile al seguente:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_10.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_thumb_4.png" width="244" height="160" /></a></p> <p>E per <em>Configuration.cs</em>:</p><pre class="csharpcode"><span class="kwrd">public</span> Configuration() { ContextKey = <span class="str">"CarContext"</span>; AutomaticMigrationsEnabled = <span class="kwrd">false</span>; MigrationsDirectory = <span class="str">@"CarDbContextMigration"</span>; }</pre><pre class="csharpcode"> </pre> <p>Aggiungiamo i corrispettivi piani di migrazione:</p> <p><em>PM&gt; Add-Migration CarDbMigration -ConfigurationTypeName MultiTenantMigration.CarDbContextMigration.Configuration <br />Scaffolding migration 'CarDbMigration'</em></p> <p><em>PM&gt; Add-Migration BusDbMigration -ConfigurationTypeName MultiTenantMigration.BusDbContextMigration.Configuration <br />Scaffolding migration 'BusDbMigration'</em></p> <p>Procediamo con l’aggiornamento del database (ricordiamo essere lo stesso per i due <em>DbContext</em>). Procediamo con <em>CarDbContext</em>:</p> <p><em>PM&gt; Update-Database -ConfigurationTypeName MultiTenantMigration.CarDbContextMigration.Configuration <br />Specify the '-Verbose' flag to view the SQL statements being applied to the target database. <br />Applying explicit migrations: [201308141834283_CarDbMigration]. <br />Applying explicit migration: 201308141834283_CarDbMigration. <br />Running Seed method.</em></p> <p>Il messaggio indica che l’aggiornamento è stato completato con successo. Passiamo ora a <em>BusDbContext</em>:</p> <p><em>PM&gt; Update-Database -ConfigurationTypeName MultiTenantMigration.BusDbContextMigration.Configuration <br />Specify the '-Verbose' flag to view the SQL statements being applied to the target database. <br />Applying explicit migrations: [201308141835410_BusDbMigration]. <br />Applying explicit migration: 201308141835410_BusDbMigration.<br />Running Seed method.</em></p> <p>A livello database:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_12.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_thumb_5.png" width="244" height="114" /></a></p> <p>In dettaglio, la tabella “MigrationHistory” è popolata con le seguenti righe (da notare la colonna <em>ContextKey</em>):</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_14.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8d783d8054a5_11B93/image_thumb_6.png" width="244" height="37" /></a></p> <p>A questo punto, tutte le successive modifiche al modello, ed i relativi piani di migrazione dovrebbero essere applicati con successo.</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101641.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/19/ef6-beta-multiple-contexts-per-database-multi-tenant-migrations.aspx Mon, 19 Aug 2013 09:38:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/08/19/ef6-beta-multiple-contexts-per-database-multi-tenant-migrations.aspx#feedback 1 http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101641.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101641.aspx EF6 (beta1) - Code First Stored Procedures Mapping http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/06/26/ef6-beta1-code-first-stored-procedures-mapping.aspx <p>Una delle features che sicuramente in molti aspettavano con la nuova release di EF è la possibilità di eseguire il mapping delle entità tramite Stored Procedures. Con la versione 6 di Entity Framework (attualmente in beta 1), abbiamo finalmente questa possibilità, e l'utilizzo è veramente immediato.</p> <p>Supponiamo di avere un Domain Model simile a quello mostrato nella figura seguente:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/WindowsLiveWriter/EF6beta1CodeFirstStoredProceduresMapping_8648/image_2.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/WindowsLiveWriter/EF6beta1CodeFirstStoredProceduresMapping_8648/image_thumb.png" width="206" height="244" /></a> </p> <p>Dove abbiamo un insieme di oggetti ereditati, ed una <em>navigation property </em>che collega l'oggeto <em>Car</em> ad una collezione di oggetti <em>Optional</em>. </p> <p>Aggiungiamo il riferimento ad EF6 utilizzando il gestore di "NuGet Packages" selezionando tra le varie opzioni "Include Prerelease" e poi selezioniamo il package "Entity Framework":</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/WindowsLiveWriter/EF6beta1CodeFirstStoredProceduresMapping_8648/image_4.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/WindowsLiveWriter/EF6beta1CodeFirstStoredProceduresMapping_8648/image_thumb_1.png" width="244" height="150" /></a> </p> <p>Eseguiamo la configurazione delle classi che compongono il nostro Domain tramite Code First Fluent Api ed aggiungiamo il codice seguente:</p> <pre class="csharpcode"> modelBuilder.Entity&lt;Domain.Car&gt;().MapToStoredProcedures(); modelBuilder.Entity&lt;Domain.Optional&gt;().MapToStoredProcedures();</pre> <p> </p> <p>Il quale "informa" il run-time di Entity Framework che per le entità "Car" ed "Optional" le operazioni di Insert\Delete\Update verranno utilizzate delle Stored Procedures (che rispondono alle convenzioni richieste da EF). </p> <p>A questo punto entra in scena EF Migrations ed il "fantastico" comando "Add-Migration", che produce tutto il codice, e non solo, necessario ad aggiornare il database:</p> <pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Up() { CreateStoredProcedure( <span class="str">"DomusDotNet.Car_Insert"</span>, p =&gt; <span class="kwrd">new</span> { Brand = p.String(maxLength: 128), Model = p.String(maxLength: 128), EngineSize = p.String(maxLength: 128), HP = p.Int(), DailyRent = p.Single(), FreeDailyKm = p.Int(), Note = p.String(maxLength: 128), }, body: <span class="str">@"INSERT [DomusDotNet].[Vehicles]([Brand], [Model], [EngineSize], [HP], [DailyRent], [FreeDailyKm], [Note]) VALUES (@Brand, @Model, @EngineSize, @HP, @DailyRent, @FreeDailyKm, @Note) DECLARE @Id int SELECT @Id = [Id] FROM [DomusDotNet].[Vehicles] WHERE @@ROWCOUNT &gt; 0 and [Id] = scope_identity() INSERT [DomusDotNet].[Cars]([Id]) VALUES (@Id) SELECT t0.[Id] FROM [DomusDotNet].[Vehicles] as t0 WHERE @@ROWCOUNT &gt; 0 and t0.[Id] = @Id"</span> ); ...</pre> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style> <p>Unico neo, se utilizzate uno schema diverso da "dbo" (anche se avete specificato tramite la nuova API HasDefaultSchema("...") lo schema corretto) bisogna modificare manualmente il nome delle Stored Procedures, altrimenti a run-time verrà generata un'eccezione.</p> <p>Scriviamo del codice di test tipo:</p> <pre class="csharpcode"><span class="kwrd">int</span> rowsAffected = 0; Domain.Car fordFocus = <span class="kwrd">new</span> Domain.Car() { Brand = <span class="str">"FORD"</span>, DailyRent = 45.0f, EngineSize = <span class="str">"1600"</span>, FreeDailyKm = 100, HP = 115, Model = <span class="str">"Focus"</span>, Note = <span class="str">"With Radio and Power Steering."</span> }; fordFocus.Optionals.Add(<span class="kwrd">new</span> Domain.Accesory() { Description = <span class="str">"Radio Sony"</span>, Removable = <span class="kwrd">true</span>, Price = 10 }); fordFocus.Optionals.Add(<span class="kwrd">new</span> Domain.Accesory() { Description = <span class="str">"Power Steering"</span>, Removable = <span class="kwrd">false</span>, Price = 0 }); <span class="kwrd">using</span> (Data.CarRentalDB db = <span class="kwrd">new</span> Data.CarRentalDB()) { db.Cars.Add(fordFocus); rowsAffected = db.SaveChanges(); }</pre> <p /><style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style>Utilizzando il nostro amico "Sql Profiler" vediamo come le operazioni di accesso alla tabella per Insert\Update\Delete utilizzano le Stored Procedures generate in precedenza: <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/WindowsLiveWriter/EF6beta1CodeFirstStoredProceduresMapping_8648/image_8.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/WindowsLiveWriter/EF6beta1CodeFirstStoredProceduresMapping_8648/image_thumb_3.png" width="244" height="130" /></a> </p> <p>Di questo ed altro parleremo in dettaglio durante l'evento <a href="mailto:EF@Work">EF@Work</a> organizzato da DomusDotNet :-)</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101596.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/06/26/ef6-beta1-code-first-stored-procedures-mapping.aspx Wed, 26 Jun 2013 10:30:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/06/26/ef6-beta1-code-first-stored-procedures-mapping.aspx#feedback 1 http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101596.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101596.aspx