Code First to a New Database (Code First per un nuovo database)

Questo video e la procedura dettagliata forniscono un'introduzione allo sviluppo Code First destinato a un nuovo database. Questo scenario include la destinazione di un database che non esiste e Code First creerà o un database vuoto a cui Code First aggiungerà nuove tabelle. Code First consente di definire il modello usando C# o VB.Net classi. Facoltativamente, è possibile eseguire una configurazione aggiuntiva usando attributi per le classi e le proprietà o usando un'API Fluent.

Guarda il video

Questo video offre un'introduzione allo sviluppo Code First destinato a un nuovo database. Questo scenario include la destinazione di un database che non esiste e Code First creerà o un database vuoto a cui Code First aggiungerà nuove tabelle. Code First consente di definire il modello usando C# o VB.Net classi. Facoltativamente, è possibile eseguire una configurazione aggiuntiva usando attributi per le classi e le proprietà o usando un'API Fluent.

Presentato da: Rowan Miller

Video: WMV | MP4 | WMV (ZIP)

Prerequisiti

Per completare questa procedura dettagliata, è necessario avere installato almeno Visual Studio 2010 o Visual Studio 2012.

Se si usa Visual Studio 2010, sarà necessario installare Anche NuGet .

1. Creare l'applicazione

Per semplificare le operazioni, si creerà un'applicazione console di base che usa Code First per eseguire l'accesso ai dati.

  • Aprire Visual Studio.
  • File -> Nuovo -> Progetto...
  • Selezionare Windows dal menu a sinistra e applicazione console
  • Immettere CodeFirstNewDatabaseSample come nome
  • seleziona OK.

2. Creare il modello

Definire un modello molto semplice usando le classi. Vengono semplicemente definiti nel file Program.cs, ma in un'applicazione reale le classi verranno suddivise in file separati e potenzialmente in un progetto separato.

Sotto la definizione della classe Program in Program.cs aggiungere le due classi seguenti.

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }

    public virtual List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public virtual Blog Blog { get; set; }
}

Si noterà che le due proprietà di spostamento (Blog.Post e Post.Blog) sono virtuali. In questo modo viene abilitata la funzionalità Caricamento differita di Entity Framework. Caricamento differita indica che il contenuto di queste proprietà verrà caricato automaticamente dal database quando si tenta di accedervi.

3. Creare un contesto

È ora possibile definire un contesto derivato, che rappresenta una sessione con il database, consentendo di eseguire query e salvare i dati. Viene definito un contesto che deriva da System.Data.Entity.DbContext ed espone un oggetto DbSet<TEntity> tipizzato per ogni classe nel modello.

A questo punto si inizia a usare i tipi di Entity Framework, quindi è necessario aggiungere il pacchetto NuGet EntityFramework.

  • Progetto:> gestisci pacchetti NuGet... Nota: se non si ha l'opzione Gestisci pacchetti NuGet, è consigliabile installare la versione più recente di NuGet
  • Selezionare la scheda Online
  • Selezionare il pacchetto EntityFramework
  • Fai clic su Install (Installa).

Aggiungere un'istruzione using per System.Data.Entity all'inizio di Program.cs.

using System.Data.Entity;

Sotto la classe Post in Program.cs aggiungere il contesto derivato seguente.

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

Ecco un elenco completo di ciò che program.cs dovrebbe ora contenere.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;

namespace CodeFirstNewDatabaseSample
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }

        public virtual List<Post> Posts { get; set; }
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public virtual Blog Blog { get; set; }
    }

    public class BloggingContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
    }
}

Questo è tutto il codice necessario per iniziare a archiviare e recuperare i dati. Ovviamente c'è un po' di tempo dietro le quinte e vedremo che in un momento, ma prima di tutto lo vediamo in azione.

4. Lettura e scrittura di dati

Implementare il metodo Main in Program.cs, come illustrato di seguito. Questo codice crea una nuova istanza del contesto e quindi la usa per inserire un nuovo blog. Usa quindi una query LINQ per recuperare tutti i blog dal database ordinati alfabeticamente in base al titolo.

class Program
{
    static void Main(string[] args)
    {
        using (var db = new BloggingContext())
        {
            // Create and save a new Blog
            Console.Write("Enter a name for a new Blog: ");
            var name = Console.ReadLine();

            var blog = new Blog { Name = name };
            db.Blogs.Add(blog);
            db.SaveChanges();

            // Display all Blogs from the database
            var query = from b in db.Blogs
                        orderby b.Name
                        select b;

            Console.WriteLine("All blogs in the database:");
            foreach (var item in query)
            {
                Console.WriteLine(item.Name);
            }

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}

È ora possibile eseguire l'applicazione e testarla.

Enter a name for a new Blog: ADO.NET Blog
All blogs in the database:
ADO.NET Blog
Press any key to exit...

Dove sono i miei dati?

Per convenzione, DbContext ha creato automaticamente un database.

  • Se è disponibile un'istanza di SQL Express locale (installata per impostazione predefinita con Visual Studio 2010), Code First ha creato il database in tale istanza
  • Se SQL Express non è disponibile, Code First proverà a usare Local DB (installato per impostazione predefinita con Visual Studio 2012)
  • Il database è denominato dopo il nome completo del contesto derivato, in questo caso CodeFirstNewDatabaseSample.BloggingContext

Queste sono solo le convenzioni predefinite e esistono diversi modi per modificare il database usato da Code First. Altre informazioni sono disponibili nell'argomento How DbContext Discovers the Model and Database Connessione ion . È possibile connettersi a questo database usando Esplora server in Visual Studio

  • Visualizzazione -> Esplora server

  • Fare clic con il pulsante destro del mouse su Data Connessione ions e selezionare Aggiungi Connessione ion...

  • Se non si è connessi a un database da Esplora server prima di dover selezionare Microsoft SQL Server come origine dati

    Select Data Source

  • Connessione a Local DB o SQL Express, a seconda di quale è stato installato

È ora possibile esaminare lo schema creato da Code First.

Schema Initial

DbContext ha elaborato le classi da includere nel modello esaminando le proprietà DbSet definite. Usa quindi il set predefinito di convenzioni Code First per determinare i nomi di tabella e colonna, determinare i tipi di dati, trovare chiavi primarie e così via. Più avanti in questa procedura dettagliata verrà illustrato come eseguire l'override di queste convenzioni.

5. Gestione delle modifiche del modello

È ora possibile apportare alcune modifiche al modello, quando si apportano queste modifiche è necessario aggiornare anche lo schema del database. A tale scopo verrà usata una funzionalità denominata Migrazioni Code First o Migrazioni per brevità.

Le migrazioni consentono di disporre di un set ordinato di passaggi che descrivono come aggiornare (e effettuare il downgrade) dello schema del database. Ognuno di questi passaggi, noto come migrazione, contiene codice che descrive le modifiche da applicare. 

Il primo passaggio consiste nell'abilitare Migrazioni Code First per il bloggingContext.

  • Strumenti -> Gestione pacchetti libreria -> Console di Gestione pacchetti

  • Eseguire il comando Enable-Migrations nella console di Gestione pacchetti

  • Al progetto è stata aggiunta una nuova cartella Migrations che contiene due elementi:

    • Configuration.cs : questo file contiene le impostazioni che verranno usate dalle migrazioni per la migrazione di BloggingContext. Non è necessario modificare nulla per questa procedura dettagliata, ma qui è possibile specificare i dati di inizializzazione, registrare i provider per altri database, modificare lo spazio dei nomi in cui vengono generate le migrazioni e così via.
    • <timestamp>_InitialCreate.cs : si tratta della prima migrazione, rappresenta le modifiche già applicate al database per portarlo da un database vuoto a uno che include le tabelle Blog e Post. Sebbene Code First crei automaticamente queste tabelle, ora che sono state acconsente esplicitamente alle migrazioni che sono state convertite in una migrazione. Code First ha anche registrato nel database locale che questa migrazione è già stata applicata. Il timestamp sul nome file viene utilizzato a scopo di ordinamento.

    A questo punto è possibile apportare una modifica al modello, aggiungere una proprietà Url alla classe Blog:

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }

    public virtual List<Post> Posts { get; set; }
}
  • Eseguire il comando Add-Migration AddUrl in Gestione pacchetti Console. Il comando Add-Migration controlla le modifiche apportate dopo l'ultima migrazione e esegue lo scaffolding di una nuova migrazione con le modifiche trovate. È possibile assegnare un nome alle migrazioni; in questo caso si chiama la migrazione 'AddUrl'. Il codice con scaffolding indica che è necessario aggiungere una colonna URL, che può contenere dati stringa, al dbo. Tabella blog. Se necessario, è possibile modificare il codice con scaffolding, ma non è necessario in questo caso.
namespace CodeFirstNewDatabaseSample.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class AddUrl : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Blogs", "Url", c => c.String());
        }

        public override void Down()
        {
            DropColumn("dbo.Blogs", "Url");
        }
    }
}
  • Eseguire il comando Update-Database nella console di Gestione pacchetti. Questo comando applicherà eventuali migrazioni in sospeso al database. La migrazione InitialCreate è già stata applicata in modo che le migrazioni applichino solo la nuova migrazione di AddUrl. Suggerimento: è possibile usare l'opzione –Verbose quando si chiama Update-Database per visualizzare il codice SQL eseguito sul database.

La nuova colonna URL viene ora aggiunta alla tabella Blogs nel database:

Schema With Url

6. Annotazioni dei dati

Fino a questo punto, Entity Framework scoprirà il modello usando le relative convenzioni predefinite, ma ci saranno momenti in cui le classi non seguono le convenzioni e dobbiamo essere in grado di eseguire altre configurazioni. Ci sono due opzioni per questo; Verranno esaminate le annotazioni dei dati in questa sezione e quindi l'API Fluent nella sezione successiva.

  • Aggiungere ora una classe User al modello
public class User
{
    public string Username { get; set; }
    public string DisplayName { get; set; }
}
  • È anche necessario aggiungere un set al contesto derivato
public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<User> Users { get; set; }
}
  • Se si tenta di aggiungere una migrazione, viene visualizzato un errore che indica che EntityType 'User' non ha una chiave definita. Definire la chiave per entityType." poiché EF non ha modo di sapere che Username deve essere la chiave primaria per User.
  • Ora si useranno annotazioni dati, quindi è necessario aggiungere un'istruzione using all'inizio di Program.cs
using System.ComponentModel.DataAnnotations;
  • Annotare ora la proprietà Username per identificare che si tratta della chiave primaria
public class User
{
    [Key]
    public string Username { get; set; }
    public string DisplayName { get; set; }
}
  • Usare il comando Add-Migration AddUser per eseguire lo scaffolding di una migrazione per applicare queste modifiche al database
  • Eseguire il comando Update-Database per applicare la nuova migrazione al database

La nuova tabella viene ora aggiunta al database:

Schema With Users

L'elenco completo delle annotazioni supportate da Entity Framework è:

7. API Fluent

Nella sezione precedente è stato esaminato l'uso delle annotazioni dei dati per integrare o ignorare ciò che è stato rilevato per convenzione. L'altro modo per configurare il modello è tramite l'API Code First Fluent.

La maggior parte della configurazione del modello può essere eseguita usando semplici annotazioni di dati. L'API Fluent è un modo più avanzato di specificare la configurazione del modello che copre tutto ciò che le annotazioni dei dati possono eseguire oltre ad alcune configurazioni più avanzate non possibili con le annotazioni dei dati. Le annotazioni dei dati e l'API Fluent possono essere usate insieme.

Per accedere all'API Fluent, eseguire l'override del metodo OnModelCreating in DbContext. Si supponga di voler rinominare la colonna in cui è archiviato User.DisplayName in in display_name.

  • Eseguire l'override del metodo OnModelCreating in BloggingContext con il codice seguente
public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<User> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .Property(u => u.DisplayName)
            .HasColumnName("display_name");
    }
}
  • Usare il comando Add-Migration ChangeDisplayName per eseguire lo scaffolding di una migrazione per applicare queste modifiche al database.
  • Eseguire il comando Update-Database per applicare la nuova migrazione al database.

La colonna DisplayName viene ora rinominata in display_name:

Schema With Display Name Renamed

Riepilogo

In questa procedura dettagliata è stato esaminato lo sviluppo Code First usando un nuovo database. È stato definito un modello usando le classi usate quindi per creare un database e archiviare e recuperare i dati. Dopo aver creato il database è stato usato Migrazioni Code First per modificare lo schema man mano che si è evoluto il modello. È stato anche illustrato come configurare un modello usando le annotazioni dei dati e l'API Fluent.