Code First Migrations http://blogs.ugidotnet.org/PietroLibroBlog/category/Code First Migrations.aspx Code First Migrations 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 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 EF Code First Migrations Beta 1 (Parte 2) http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/04/ef-code-first-migrations-beta-1-parte-2.aspx <p>In questa seconda parte proveremo ad eseguire gli stessi passi eseguiti <a href="http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/01/ef-code-first-migrations-beta-1-parte-1.aspx" target="_blank">in precedenza</a> utilizzando “la migrazione automatica dello schema”. Per comodità riporto la classe <em>DbContext</em> ed il semplice Object Model utilizzato per la definizione dello schema del database:</p> <pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">class</span> OfficeContext : DbContext { <span class="kwrd">public</span> OfficeContext() : <span class="kwrd">base</span>(<span class="str">"OfficeDB"</span>) { } <span class="kwrd">public</span> DbSet&lt;Employee&gt; Employees { 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); } <span class="kwrd">static</span> OfficeContext() { Database.SetInitializer&lt;OfficeContext&gt;(<span class="kwrd">null</span>); } } <span class="kwrd">public</span> <span class="kwrd">class</span> Employee { <span class="kwrd">public</span> <span class="kwrd">int</span> Id { get; set; } <span class="kwrd">public</span> String Name { get; set; } <span class="kwrd">public</span> String Surname { get; set; } <span class="kwrd">public</span> String Role { get; set; } }</pre> <style type="text/css"><![CDATA[ .csharpcode { background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small } .csharpcode pre { background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small } .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; margin: 0em; width: 100% } .csharpcode .lnum { color: #606060 }]]></style> <p>Avendo aggiunto <em>EntityFramework.Migrations</em> in precedenza, per continuare, dobbiamo aprire la classe <em>Configuration.cs</em> all’interno della cartella <em>Migrations</em> ed impostare la proprietà <em>AutomaticMigrationsEnabled</em> a <em>true</em>:</p> <pre class="csharpcode"><span class="kwrd">public</span> Configuration() { AutomaticMigrationsEnabled = <span class="kwrd">true</span>; AutomaticMigrationDataLossAllowed = <span class="kwrd">false</span>; }</pre> <p /><style type="text/css"><![CDATA[ .csharpcode { background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small } .csharpcode pre { background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small } .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; margin: 0em; width: 100% } .csharpcode .lnum { color: #606060 }]]></style>Inoltre impostiamo la proprietà <em>AutomaticMigrationDataLossAllowed=false</em>: in questo modo un’eccezione verrà sollevata nel caso in cui la migrazione dello schema comporti una perdita di dati. Nell’<em>override</em> del metodo <em>Seed</em> aggiungiamo del codice per inserire delle righe dopo la generazione\migrazione dello schema: <pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Seed(OfficeContext context) { context.AddOrUpdate( <span class="kwrd">new</span> Employee() { Name = <span class="str">"Mario"</span>, Surname = <span class="str">"Rossi"</span>, Role = <span class="str">"Administrator"</span> }, <span class="kwrd">new</span> Employee() { Name = <span class="str">"Giulio"</span>, Surname = <span class="str">"Verdi"</span>, Role = <span class="str">"Store Manager"</span> }, <span class="kwrd">new</span> Employee() { Name = <span class="str">"Pietro"</span>, Surname = <span class="str">"Libro"</span>, Role = <span class="str">"Art Director"</span> } ); }</pre> <p /><style type="text/css"><![CDATA[ .csharpcode { background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small } .csharpcode pre { background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small } .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; margin: 0em; width: 100% } .csharpcode .lnum { color: #606060 }]]></style>A differenza della procedura manuale, digitiamo direttamente il comando <em>update-database </em>nella console di NuGet, eventualmente utilizzato i parametri –<em>verbose</em>  o <em>-script</em> rispettivamente per visualizzare o creare un file di <em>.sql</em> con i comandi generati da VS: <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/63a1691fa2c0_8580/image_4.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/63a1691fa2c0_8580/image_thumb_1.png" width="244" height="210" /></a></p> <p>Come per la prima parte, utilizzando ad esempio SQL Management Studio, vediamo che il lavoro “sporco” sia stato eseguito correttamente come ci aspettavamo:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/63a1691fa2c0_8580/image_6.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/63a1691fa2c0_8580/image_thumb_2.png" width="244" height="104" /></a></p> <p>Ora, se volessimo apportare le stesse modifiche allo schema del modello dati, come nel caso del <a href="http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/01/ef-code-first-migrations-beta-1-parte-1.aspx" target="_blank">post precedente</a>, dovremmo ritornare “in modalità manuale” (in quanto, in questa modalità non possiamo specificare i valori di default per i nuovi campi o utilizzare codice SQL custom) quindi  utilizzando il comando <em>Add-Migration</em> e relativi parametri. Ovviamente abbiamo già discusso su come eseguire questi passaggi e non staremo qui a ripeterli:  IMHO la migrazione automatica non mi ha entusiasmato molto a differenza di quella manuale dove è possibile intervenire in diversi punti.</p> <p>Proviamo ora ad eliminare (o commentare) la proprietà <em>Surname</em>  dall’entità <em>Employee</em>:</p> <pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">class</span> Employee { <span class="kwrd">public</span> <span class="kwrd">int</span> Id { get; set; } <span class="kwrd">public</span> String Name { get; set; } <span class="kwrd">public</span> String Role { get; set; } }</pre> <style type="text/css"><![CDATA[ .csharpcode { background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small } .csharpcode pre { background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small } .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; margin: 0em; width: 100% } .csharpcode .lnum { color: #606060 }]]></style> <p>Commentiamo il codice presente nel <em>Seed </em>ed eseguiamo il comando <em>update-database</em>:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/63a1691fa2c0_8580/image_8.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/63a1691fa2c0_8580/image_thumb_3.png" width="244" height="107" /></a></p> <p>Entity Framework ci avverte che l’aggiornamento non è stato completato perché potrebbe verificarsi una perdita di dati, ma allo stesso tempo ci suggerisce di utilizzare il parametro <em>–force </em>per forzare l’aggiornamento della base di dati (con conseguente <em>data loss</em>). Ok.</p> <p>Oltre a commentare il codice (non proprio una <em>best practice</em>) per evitare di aggiungere dati duplicati tramite <em>l’AddOrUpdate</em> del <em>Seed  </em>è sufficiente istruire VS con una <em>Func&lt;TEntity,Object&gt;</em> al fine di specificare quali proprietà devono essere considerate per identificare un record come duplicato:</p> <pre class="csharpcode">System.Linq.Expressions.Expression&lt;Func&lt;Employee, <span class="kwrd">object</span>&gt;&gt; identify = n =&gt; <span class="kwrd">new</span> { n.Name, n.Role }; context.AddOrUpdate(identify, <span class="kwrd">new</span> Employee() { Name = <span class="str">"Mario"</span>, Role = <span class="str">"Administrator"</span> }, <span class="kwrd">new</span> Employee() { Name = <span class="str">"Giulio"</span>, Role = <span class="str">"Store Manager"</span> }, <span class="kwrd">new</span> Employee() { Name = <span class="str">"Pietro"</span>, Role = <span class="str">"Art Director"</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><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100600.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/04/ef-code-first-migrations-beta-1-parte-2.aspx Sun, 04 Dec 2011 08:42:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/04/ef-code-first-migrations-beta-1-parte-2.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100600.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100600.aspx EF Code First Migrations Beta 1 (Parte 1) http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/01/ef-code-first-migrations-beta-1-parte-1.aspx <p> </p> <p>Finalmente sono riuscito a trovare qualche minuto per buttare giù qualche riga a riguardo di EF Code First Migrations (da qualche giorno disponibile in  beta 1). Per chi usa l’approccio Code First l’aggiornamento del modello e della base di dati sottostante (soprattutto quando contiene dati)  è un grosso problema. Proviamo a testare il funzionamento del “pacchetto” su un modello molto semplice come il seguente, in un progetto console C#:</p> <pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">class</span> OfficeContext : DbContext { <span class="kwrd">public</span> OfficeContext() : <span class="kwrd">base</span>(<span class="str">"OfficeDB"</span>) { } <span class="kwrd">public</span> DbSet&lt;Employee&gt; Employees { 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); } <span class="kwrd">static</span> OfficeContext() { Database.SetInitializer&lt;OfficeContext&gt;(<span class="kwrd">null</span>); } } <span class="kwrd">public</span> <span class="kwrd">class</span> Employee { <span class="kwrd">public</span> <span class="kwrd">int</span> Id { get; set; } <span class="kwrd">public</span> String Name { get; set; } <span class="kwrd">public</span> String Surnamte { get; set; } <span class="kwrd">public</span> String Role { 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>Aggiungiamo al progetto un file <em>App.Config</em> con una stringa di connessione simile alla seguente:</p> <pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">="OfficeDB"</span> <span class="attr">connectionString</span><span class="kwrd">="Data Source=(local)\SQLEXPRESS;Initial Catalog=OfficeDB;Integrated Security=True;"</span> <span class="attr">providerName</span><span class="kwrd">="System.Data.SqlClient"</span><span class="kwrd">/&gt;</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>Per come abbiamo configurato il <em>DBContext</em> nessun database verrà generato, anzi, a <em>runtime</em> avremo un’eccezione di questo tipo:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_6.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb_2.png" width="244" height="114" /></a></p> <p>Procediamo con l’installazione via NuGet del Package <em>EntityFramework.Migrations</em> (<em>Code First Migrations Beta 1, ver. 0.8.0.0</em>):</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb.png" width="244" height="164" /></a></p> <p>Durante il processo di installazione viene automaticamente aggiunta al progetto una nuova cartella, “Migrations” contenente il file <em>Configuration.cs </em>(derivata da <em>DbMigrationsConfiguration&lt;T&gt;</em> dove T è la classe <em>OfficeContext</em>) nel quale possiamo specificare, ad esempio, se utilizzare la “migrazione automatica del modello” (vedremo in seguito) tramite la proprietà <em>AutomaticMigrationsEnabled </em>(<em>false</em> di default), se continuare o meno una migrazione dello schema anche in presenza di perdita dei dati, <em>AutomaticMigrationDataLossAllowed, </em>o se sollevare un’eccezione. Inoltre tramite <em>l’override</em> di <em>Seed </em>è possibile specificare se aggiungere dopo la generazione\migrazione dello schema, dei dati al database (avendo avuto qualche problema nei test con l’estensione <em>AddOrUpdate</em> preferisco utilizzare codice SQL per il momento <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/wlEmoticon-smile_2.png" />) . La classe <em>Configuration</em> sarà così definita:</p> <pre class="csharpcode"> <span class="kwrd">internal</span> <span class="kwrd">sealed</span> <span class="kwrd">class</span> Configuration : DbMigrationsConfiguration&lt;OfficeContext&gt; { <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Seed(OfficeContext context) { <span class="kwrd">base</span>.Seed(context); } <span class="kwrd">public</span> Configuration() { AutomaticMigrationsEnabled = <span class="kwrd">false</span>; AutomaticMigrationDataLossAllowed = <span class="kwrd">false</span>; } }</pre> <p>Ora, per eseguire la creazione del database, dobbiamo aggiungere “a scaffale” la nostra prima “migrazione”(ovvero la generazione del database): così facendo, oltre a richiamare i metodi per la generazione del database, potremmo eseguire nel tempo degli <em>Upgrade</em> e <em>Downgrade</em> utilizzando i vari piani di migrazione che andremo a creare: se uniamo a quanto detto TFS, penso non ci sia altro da aggiungere. Nella console di NuGet (Package Manager Console) digitiamo : <em>Add-Migration [parametro] </em>dove parametro è un etichetta che identifica in modo univoco la migrazione che stiamo aggiungendo. Nel nostro caso <em>parametro</em>=<em>OfficeDBFirstMigration.  </em>Se tutto procede senza errori, la schermata della console di NuGet dovrebbe essere simile alla seguente:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_8.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb_3.png" width="244" height="120" /></a></p> <p>Al progetto viene aggiunto un un file <em>xxxx_OfficeDBFirstMigration.cs</em> contenente uno “Snapshot” del modello Code First del database da creare definito dalla classe <em>DbContext</em> (<em>OfficeContext</em> per il caso specifico). Per generare il database, digitiamo il comando <em>Update-Database </em>(che prende in considerazione l’ultimo file di migrazione “Pending”,  “a scaffale”)<em>, </em>eventualmente aggiungendo il parametro <em>–Verbose </em>per visualizzare i comandi SQL generati, oppure il parametro <em>–Script</em> per generare un file <em>.sql </em>da scambiare con gli altri membri del team o eventualmente da aggiungere su TFS:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_10.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb_4.png" width="244" height="120" /></a></p> <p>Utilizzando SQL Management Studio possiamo vedere come il database sia stato creato secondo le nostre specifiche (le colonne sono state aggiunge utilizzando le convenzioni di EF):</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_12.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb_5.png" width="244" height="237" /></a></p> <p> </p><p>Prima di continuare, facciamo un passo indietro e  “spulciamo” il contenuto della classe <em>OfficeDBFirstMigration</em> generata dal comando <em>Add-Migration</em>:</p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> OfficeDBFirstMigration : DbMigration { <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Up() { CreateTable( <span class="str">"Employees"</span>, c =&gt; <span class="kwrd">new</span> { Id = c.Int(nullable: <span class="kwrd">false</span>, identity: <span class="kwrd">true</span>), Name = c.String(), Surname = c.String(), Role = c.String(), }) .PrimaryKey(t =&gt; t.Id); CreateTable( <span class="str">"EdmMetadata"</span>, c =&gt; <span class="kwrd">new</span> { Id = c.Int(nullable: <span class="kwrd">false</span>, identity: <span class="kwrd">true</span>), ModelHash = c.String(), }) .PrimaryKey(t =&gt; t.Id); Sql(<span class="str">"INSERT INTO Employees ([Name],[Surname],[Role]) VALUES ('Pietro','Libro','Art Director')"</span>); Sql(<span class="str">"INSERT INTO Employees ([Name],[Surname],[Role]) VALUES ('Mario','Rossi','Administrator')"</span>); Sql(<span class="str">"INSERT INTO Employees ([Name],[Surname],[Role]) VALUES ('Giulio','Verdi','Store Manager')"</span>); } <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Down() { DropTable(<span class="str">"EdmMetadata"</span>); DropTable(<span class="str">"Employees"</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><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>Nella classe è stato generato l’override dei metodi <em>Up</em> e <em>Down </em>(sembra il motivo di una canzone di qualche anno fa <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/wlEmoticon-smile_2.png" /> ) . <em>Up</em>, come è facile intuire, contiene il codice eseguito per l’esecuzione dell’upgrade dello schema della base dati, <em>Down</em>, il codice eseguito per effettuare  il downgrade ad una versione precedente della base dati. La lettura del codice è abbastanza semplice, ed in questo punto possiamo intervenire per specificare manualmente (ove necessario) quanto non automaticamente generato da VS: ad esempio avremmo potuto aggiungere del codice per specificare degli indici  (automatico per le chiavi primarie, Id nello specifico) o delle<em> </em>Foreign Key. Inoltre possiamo aggiungere del codice SQL personalizzato utilizzando il metodo SQL (…). Utilizziamo questo metodo per aggiungere tre righe alla tabella <em>Employees</em>. </p> <p>Eseguendo il nostro progetto , il risultato che otteniamo è mostrato figura:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_16.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb_7.png" width="244" height="132" /></a></p> <p>Modifichiamo il modello dati, nello specifico l’entità <em>Employee</em>: aggiungiamo la colonna <em>CardID</em> (di tipo stringa) contenente il numero identificativo stampato sul badge di ogni dipendente, ed impostiamo tramite <em>override</em> dell’<em>OnModelBuilder</em> la lunghezza massima del campo a 20 caratteri. Inizialmente tutti i dipendenti dovranno avere un identificativo del tipo “00000-00000”. Procediamo con il comando <em>Add-Migration OfficeDBSecondMigration</em>, per aggiungere un nuovo piano di migrazione, ovvero un nuovo file .cs del tipo <em>xxxxxx_OfficeDBSecondMigration.cs</em>, che andiamo immediatamente ad ispezionare per aggiungere del codice personalizzato (per impostare il d<em>efault value</em>) prima di procedere con l’aggiornamento:</p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> OfficeDBsecondMigration : DbMigration { <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Up() { AddColumn(<span class="str">"Employees"</span>, <span class="str">"CardID"</span>, c =&gt; c.String(nullable: <span class="kwrd">false</span>, defaultValue: <span class="str">"00000-00000"</span>, maxLength:20)); } <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Down() { DropColumn(<span class="str">"Employees"</span>, <span class="str">"CardID"</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><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>(Nota: invertendo l’ordine tra d<em>efaultValue</em> e <em>maxLength </em>sull’ambiente di test viene sollevata un’eccezione <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-sadsmile" alt="Triste" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/wlEmoticon-sadsmile_2.png" />, d’altra parte non sarebbe una beta <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/wlEmoticon-smile_2.png" />). Procediamo con l’aggiornamento (Up<em>date-Database</em>). Vediamo cosa è successo: </p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_18.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb_8.png" width="244" height="81" /></a></p> <p>Quello che ci aspettavamo. Utilizzando solo Code First, questo processo di aggiornamento sarebbe risultato distruttivo e comunque avrebbe richiesto un certo <em>effort </em>di modifiche “a manina”. Prima di concludere cerchiamo di aumentare la complessità del modello aggiungendo una tabella <em>Roles </em>ed una relazione uno-a-molti tra le entità <em>Employee</em> e <em>Role:</em></p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_20.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb_9.png" width="244" height="110" /></a></p> <p>Mettiamo <em>in pending</em> il nuovo schema dati (<em>Add-Migration OfficeDBThirdMigration</em>):</p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> OfficeDBThirdMigration : DbMigration { <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Up() { CreateTable( <span class="str">"Roles"</span>, c =&gt; <span class="kwrd">new</span> { Id = c.Int(nullable: <span class="kwrd">false</span>, identity: <span class="kwrd">true</span>), Description = c.String(), }) .PrimaryKey(t =&gt; t.Id); AddColumn(<span class="str">"Employees"</span>, <span class="str">"Role_Id"</span>, c =&gt; c.Int()); AddForeignKey(<span class="str">"Employees"</span>, <span class="str">"Role_Id"</span>, <span class="str">"Roles"</span>, <span class="str">"Id"</span>); CreateIndex(<span class="str">"Employees"</span>, <span class="str">"Role_Id"</span>); DropColumn(<span class="str">"Employees"</span>, <span class="str">"Role"</span>); Sql(<span class="str">"INSERT INTO Roles (Description) VALUES ('Administrator')"</span>); Sql(<span class="str">"INSERT INTO Roles (Description) VALUES ('Store Manager')"</span>); Sql(<span class="str">"INSERT INTO Roles (Description) VALUES ('Art Director')"</span>); Sql(<span class="str">"UPDATE Employees SET Role_ID = 1 WHERE Name='Mario' AND Surname ='Rossi'"</span>); Sql(<span class="str">"UPDATE Employees SET Role_ID = 2 WHERE Name='Giulio' AND Surname ='Verdi'"</span>); Sql(<span class="str">"UPDATE Employees SET Role_ID = 3 WHERE Name='Pietro' AND Surname ='Libro'"</span>); } <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Down() { AddColumn(<span class="str">"Employees"</span>, <span class="str">"Role"</span>, c =&gt; c.String()); DropIndex(<span class="str">"Employees"</span>, <span class="kwrd">new</span>[] { <span class="str">"Role_Id"</span> }); DropForeignKey(<span class="str">"Employees"</span>, <span class="str">"Role_Id"</span>, <span class="str">"Roles"</span>, <span class="str">"Id"</span>); DropColumn(<span class="str">"Employees"</span>, <span class="str">"Role_Id"</span>); DropTable(<span class="str">"Roles"</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>A cui abbiamo aggiunto del codice SQL custom. Un ultimo <em>Update-Database</em> ed il gioco è fatto:</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_22.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb_10.png" width="192" height="244" /></a></p> <p>Il risultato ovviamente non cambia <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sorriso" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/wlEmoticon-smile_2.png" /></p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_24.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/8f18e8ce678b_12CCB/image_thumb_11.png" width="244" height="85" /></a></p> <p>Per eseguire l’upgrade-downgrade del modello dati è sufficiente invocare il metodo<em> Update-Database –targetmigration [parametro] </em>dove <em>[parametro]</em> è uno dei nomi utilizzati in precedenza (ad esempio <em>OfficeDBFirstMigration</em> ). Vedremo nel prossimo post il funzionamento della modalità “automatica” di migrazione.</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100590.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/01/ef-code-first-migrations-beta-1-parte-1.aspx Thu, 01 Dec 2011 23:59:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/01/ef-code-first-migrations-beta-1-parte-1.aspx#feedback 1 http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100590.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100590.aspx Code First Migrations: Beta 1 Released http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/11/30/code-first-migrations-beta-1-released.aspx <p>Rilasciata la versione Beta 1 di Code First Migrations. Tutti i dettagli <a target="_blank" href="http://blogs.msdn.com/b/adonet/archive/2011/11/29/code-first-migrations-beta-1-released.aspx">qui</a>. La semplicità di utilizzo è veramente notevole <img src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/PietroLibroBlog/Windows-Live-Writer/Code-First-Migrations-Beta-1-Released_A6E1/wlEmoticon-smile_2.png" alt="Sorriso" class="wlEmoticon wlEmoticon-smile" style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" />.</p><img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100581.aspx" width="1" height="1" /> Pietro Libro http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/11/30/code-first-migrations-beta-1-released.aspx Wed, 30 Nov 2011 12:52:00 GMT http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/11/30/code-first-migrations-beta-1-released.aspx#feedback http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100581.aspx http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100581.aspx