Condividi tramite


Esercitazione: Usare Migrazioni di Entity Framework in un'app MVC ASP.NET e distribuirla in Azure

Finora l'applicazione Web di esempio Contoso University è stata eseguita localmente in IIS Express nel computer di sviluppo. Per rendere disponibile un'applicazione reale per gli altri utenti da usare tramite Internet, è necessario distribuirla in un provider di hosting Web. In questa esercitazione si abilitano le migrazioni Code First e si distribuisce l'applicazione nel cloud in Azure:

  • Abilitare Migrazioni Code First. La funzionalità Migrazioni consente di modificare il modello di dati e di distribuire le modifiche nell'ambiente di produzione aggiornando lo schema del database senza dover eliminare e ricreare il database.
  • Distribuisci in Azure. Questo passaggio è facoltativo; è possibile continuare con le esercitazioni rimanenti senza aver distribuito il progetto.

È consigliabile usare un processo di integrazione continua con il controllo del codice sorgente per la distribuzione, ma questa esercitazione non tratta tali argomenti. Per ulteriori informazioni, vedere Distribuire automaticamente un microservizio cloud-native .NET con GitHub Actions e Azure Pipelines.

In questa esercitazione:

  • Abilitare le migrazioni Code First
  • Distribuire l'app in Azure (facoltativo)

Prerequisiti

Abilitare le migrazioni Code First

Quando si sviluppa una nuova applicazione, il modello di dati cambia di frequente e, a ogni cambiamento, non è più sincronizzato con il database. Entity Framework è stato configurato per eliminare e ricreare automaticamente il database ogni volta che si modifica il modello di dati. Quando si aggiungono, rimuovono o modificano le classi di entità o si modifica la DbContext classe, al successivo esecuzione dell'applicazione elimina automaticamente il database esistente, ne viene creato uno nuovo che corrisponde al modello e ne esegue il seeding con i dati di test.

Questo metodo che consiste nel mantenere il database sincronizzato con il modello di dati funziona bene fino a quando non si distribuisce l'applicazione nell'ambiente di produzione. Quando l'applicazione è in esecuzione nell'ambiente di produzione, in genere archivia i dati da mantenere e non si vuole perdere tutto ogni volta che si apporta una modifica, ad esempio l'aggiunta di una nuova colonna. La funzionalità Migrazioni Code First risolve questo problema consentendo a Code First di aggiornare lo schema del database invece di eliminare e creare nuovamente il database. In questa esercitazione si distribuirà l'applicazione e si preparerà per abilitare le migrazioni.

  1. Disabilitare l'inizializzatore configurato in precedenza commentando o eliminando l'elemento contexts aggiunto al file Web.config dell'applicazione.

    <entityFramework>
      <!--<contexts>
        <context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">
          <databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" />
        </context>
      </contexts>-->
      <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
        <parameters>
          <parameter value="v11.0" />
        </parameters>
      </defaultConnectionFactory>
      <providers>
        <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      </providers>
    </entityFramework>
    
  2. Nel file Web.config dell'applicazione modificare anche il nome del database nel stringa di connessione in ContosoUniversity2.

    <connectionStrings>
      <add name="SchoolContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=ContosoUniversity2;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
    </connectionStrings>
    

    Questa modifica configura il progetto in modo che la prima migrazione crei un nuovo database. Questo non è obbligatorio, ma si vedrà più avanti perché è una buona idea.

  3. Nel menu Strumenti selezionare Gestione pacchetti NuGet>Console di Gestione pacchetti.

  4. PM> Al prompt immettere i comandi seguenti:

    enable-migrations
    add-migration InitialCreate
    

    Il enable-migrations comando crea una cartella Migrations nel progetto ContosoUniversity e inserisce in tale cartella un file Configuration.cs che è possibile modificare per configurare le migrazioni.

    Se non è stato eseguito il passaggio precedente che indica di modificare il nome del database, Le migrazioni troveranno il database esistente ed eseguono automaticamente il add-migration comando. Ciò significa che non si eseguirà un test del codice delle migrazioni prima di distribuire il database. In un secondo momento, quando si esegue il update-database comando non verrà eseguita alcuna operazione perché il database esiste già.

    Aprire il file ContosoUniversity\Migrations\Configuration.cs . Analogamente alla classe di inizializzazione illustrata in precedenza, la Configuration classe include un Seed metodo .

    internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.DAL.SchoolContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }
    
        protected override void Seed(ContosoUniversity.DAL.SchoolContext context)
        {
            //  This method will be called after migrating to the latest version.
    
            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
    

    Lo scopo del metodo Seed è consentire di inserire o aggiornare i dati di test dopo che Code First crea o aggiorna il database. Il metodo viene chiamato quando viene creato il database e ogni volta che lo schema del database viene aggiornato dopo la modifica di un modello di dati.

Configurare il metodo Seed

Quando si rilascia e si ricrea il database per ogni modifica del modello di dati, si usa il metodo della Seed classe di inizializzatori per inserire i dati di test, perché dopo che ogni modifica del modello il database viene eliminato e tutti i dati di test vengono persi. Con Migrazioni Code First, i dati di test vengono conservati dopo le modifiche del database, pertanto non è in genere necessario includere i dati di test nel metodo Seed. In effetti, non si vuole che il Seed metodo inserisca i dati di test se si usano Migrazioni per distribuire il database nell'ambiente di produzione, perché il Seed metodo verrà eseguito nell'ambiente di produzione. In tal caso, si vuole che il Seed metodo inserisca nel database solo i dati necessari nell'ambiente di produzione. Ad esempio, è possibile che il database includa i nomi effettivi dei reparti nella Department tabella quando l'applicazione diventa disponibile nell'ambiente di produzione.

Per questa esercitazione si useranno Migrazioni per la distribuzione, ma il Seed metodo inserirà comunque i dati di test per semplificare il funzionamento delle funzionalità dell'applicazione senza dover inserire manualmente molti dati.

  1. Sostituire il contenuto del file Configuration.cs con il codice seguente, che carica i dati di test nel nuovo database.

    namespace ContosoUniversity.Migrations
    {
        using ContosoUniversity.Models;
        using System;
        using System.Collections.Generic;
        using System.Data.Entity;
        using System.Data.Entity.Migrations;
        using System.Linq;
    
        internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.DAL.SchoolContext>
        {
            public Configuration()
            {
                AutomaticMigrationsEnabled = false;
            }
    
            protected override void Seed(ContosoUniversity.DAL.SchoolContext context)
            {
                var students = new List<Student>
                {
                    new Student { FirstMidName = "Carson",   LastName = "Alexander", 
                        EnrollmentDate = DateTime.Parse("2010-09-01") },
                    new Student { FirstMidName = "Meredith", LastName = "Alonso",    
                        EnrollmentDate = DateTime.Parse("2012-09-01") },
                    new Student { FirstMidName = "Arturo",   LastName = "Anand",     
                        EnrollmentDate = DateTime.Parse("2013-09-01") },
                    new Student { FirstMidName = "Gytis",    LastName = "Barzdukas", 
                        EnrollmentDate = DateTime.Parse("2012-09-01") },
                    new Student { FirstMidName = "Yan",      LastName = "Li",        
                        EnrollmentDate = DateTime.Parse("2012-09-01") },
                    new Student { FirstMidName = "Peggy",    LastName = "Justice",   
                        EnrollmentDate = DateTime.Parse("2011-09-01") },
                    new Student { FirstMidName = "Laura",    LastName = "Norman",    
                        EnrollmentDate = DateTime.Parse("2013-09-01") },
                    new Student { FirstMidName = "Nino",     LastName = "Olivetto",  
                        EnrollmentDate = DateTime.Parse("2005-08-11") }
                };
                students.ForEach(s => context.Students.AddOrUpdate(p => p.LastName, s));
                context.SaveChanges();
    
                var courses = new List<Course>
                {
                    new Course {CourseID = 1050, Title = "Chemistry",      Credits = 3, },
                    new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3, },
                    new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3, },
                    new Course {CourseID = 1045, Title = "Calculus",       Credits = 4, },
                    new Course {CourseID = 3141, Title = "Trigonometry",   Credits = 4, },
                    new Course {CourseID = 2021, Title = "Composition",    Credits = 3, },
                    new Course {CourseID = 2042, Title = "Literature",     Credits = 4, }
                };
                courses.ForEach(s => context.Courses.AddOrUpdate(p => p.Title, s));
                context.SaveChanges();
    
                var enrollments = new List<Enrollment>
                {
                    new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").ID, 
                        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID, 
                        Grade = Grade.A 
                    },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").ID,
                        CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID, 
                        Grade = Grade.C 
                     },                            
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").ID,
                        CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID, 
                        Grade = Grade.B
                     },
                     new Enrollment { 
                         StudentID = students.Single(s => s.LastName == "Alonso").ID,
                        CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment { 
                         StudentID = students.Single(s => s.LastName == "Alonso").ID,
                        CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment {
                        StudentID = students.Single(s => s.LastName == "Alonso").ID,
                        CourseID = courses.Single(c => c.Title == "Composition" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Anand").ID,
                        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Anand").ID,
                        CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
                        Grade = Grade.B         
                     },
                    new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
                        CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
                        Grade = Grade.B         
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Li").ID,
                        CourseID = courses.Single(c => c.Title == "Composition").CourseID,
                        Grade = Grade.B         
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Justice").ID,
                        CourseID = courses.Single(c => c.Title == "Literature").CourseID,
                        Grade = Grade.B         
                     }
                };
    
                foreach (Enrollment e in enrollments)
                {
                    var enrollmentInDataBase = context.Enrollments.Where(
                        s =>
                             s.Student.ID == e.StudentID &&
                             s.Course.CourseID == e.CourseID).SingleOrDefault();
                    if (enrollmentInDataBase == null)
                    {
                        context.Enrollments.Add(e);
                    }
                }
                context.SaveChanges();
            }
        }
    }
    

    Il metodo Seed accetta l'oggetto contesto di database come parametro di input e il codice nel metodo usa tale oggetto per aggiungere nuove entità al database. Per ogni tipo di entità, il codice crea una raccolta di nuove entità, le aggiunge alla proprietà DbSet appropriata e quindi salva le modifiche nel database. Non è necessario chiamare il metodo SaveChanges dopo ogni gruppo di entità, come avviene qui, ma ciò consente di individuare l'origine di un problema se si verifica un'eccezione durante la scrittura del codice nel database.

    Alcune istruzioni che inseriscono dati usano il metodo AddOrUpdate per eseguire un'operazione "upsert". Poiché il Seed metodo viene eseguito ogni volta che si esegue il update-database comando, in genere dopo ogni migrazione, non è possibile inserire solo i dati, perché le righe che si sta tentando di aggiungere saranno già presenti dopo la prima migrazione che crea il database. L'operazione "upsert" impedisce errori che si verificherebbero se si tenta di inserire una riga già esistente, ma esegue l'override di tutte le modifiche apportate ai dati apportati durante il test dell'applicazione. Con i dati di test in alcune tabelle potrebbe non essere necessario eseguire questa operazione: in alcuni casi quando si modificano i dati durante il test si vuole che le modifiche rimangano dopo gli aggiornamenti del database. In tal caso si vuole eseguire un'operazione di inserimento condizionale: inserire una riga solo se non esiste già. Il metodo Seed usa entrambi gli approcci.

    Il primo parametro passato al metodo AddOrUpdate specifica la proprietà da utilizzare per verificare se esiste già una riga. Per i dati degli studenti di test specificati, la LastName proprietà può essere usata a questo scopo perché ogni cognome nell'elenco è univoco:

    context.Students.AddOrUpdate(p => p.LastName, s)
    

    Questo codice presuppone che i cognome siano univoci. Se si aggiunge manualmente uno studente con un cognome duplicato, si otterrà l'eccezione seguente alla successiva esecuzione di una migrazione:

    La sequenza contiene più di un elemento

    Per informazioni su come gestire dati ridondanti, ad esempio due studenti denominati "Alexander Carson", vedere Seeding and Debugging Entity Framework (EF) DBs (EF) nel blog di Rick Anderson. Per altre informazioni sul AddOrUpdate metodo, vedere Prendersi cura del metodo AddOrUpdate di EF 4.3 nel blog di Julie Lerman.

    Il codice che crea Enrollment entità presuppone che il valore sia presente ID nelle entità della students raccolta, anche se non è stata impostata tale proprietà nel codice che crea la raccolta.

    new Enrollment { 
        StudentID = students.Single(s => s.LastName == "Alexander").ID, 
        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID, 
        Grade = Grade.A 
    },
    

    È possibile utilizzare la ID proprietà qui perché il ID valore viene impostato quando si chiama SaveChanges per la students raccolta. Ef ottiene automaticamente il valore della chiave primaria quando inserisce un'entità nel database e aggiorna la ID proprietà dell'entità in memoria.

    Il codice che aggiunge ogni Enrollment entità al Enrollments set di entità non usa il AddOrUpdate metodo . Controlla se un'entità esiste già e inserisce l'entità se non esiste. Questo approccio manterrà le modifiche apportate a un livello di registrazione usando l'interfaccia utente dell'applicazione. Il codice esegue il ciclo di ogni membro dell'elenco Enrollment e, se la registrazione non viene trovata nel database, aggiunge la registrazione al database. La prima volta che si aggiorna il database, il database sarà vuoto, quindi verrà aggiunta ogni registrazione.

    foreach (Enrollment e in enrollments)
    {
        var enrollmentInDataBase = context.Enrollments.Where(
            s => s.Student.ID == e.Student.ID &&
                 s.Course.CourseID == e.Course.CourseID).SingleOrDefault();
        if (enrollmentInDataBase == null)
        {
            context.Enrollments.Add(e);
        }
    }
    
  2. Compilare il progetto.

Eseguire la prima migrazione

Quando è stato eseguito il add-migration comando, le migrazioni hanno generato il codice che creava il database da zero. Questo codice si trova anche nella cartella Migrations , nel file denominato <timestamp>_InitialCreate.cs. Il Up metodo della InitialCreate classe crea le tabelle di database che corrispondono ai set di entità del modello di dati e il Down metodo li elimina.

public partial class InitialCreate : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.Course",
            c => new
                {
                    CourseID = c.Int(nullable: false),
                    Title = c.String(),
                    Credits = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.CourseID);
        
        CreateTable(
            "dbo.Enrollment",
            c => new
                {
                    EnrollmentID = c.Int(nullable: false, identity: true),
                    CourseID = c.Int(nullable: false),
                    StudentID = c.Int(nullable: false),
                    Grade = c.Int(),
                })
            .PrimaryKey(t => t.EnrollmentID)
            .ForeignKey("dbo.Course", t => t.CourseID, cascadeDelete: true)
            .ForeignKey("dbo.Student", t => t.StudentID, cascadeDelete: true)
            .Index(t => t.CourseID)
            .Index(t => t.StudentID);
        
        CreateTable(
            "dbo.Student",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    LastName = c.String(),
                    FirstMidName = c.String(),
                    EnrollmentDate = c.DateTime(nullable: false),
                })
            .PrimaryKey(t => t.ID);
        
    }
    
    public override void Down()
    {
        DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student");
        DropForeignKey("dbo.Enrollment", "CourseID", "dbo.Course");
        DropIndex("dbo.Enrollment", new[] { "StudentID" });
        DropIndex("dbo.Enrollment", new[] { "CourseID" });
        DropTable("dbo.Student");
        DropTable("dbo.Enrollment");
        DropTable("dbo.Course");
    }
}

Le migrazioni chiamano il metodo Up per implementare le modifiche al modello di dati per una migrazione. Quando si immette un comando per annullare l'aggiornamento, le migrazioni chiamano il metodo Down.

Si tratta della migrazione iniziale creata quando è stato immesso il add-migration InitialCreate comando . Il parametro (InitialCreate nell'esempio) viene usato per il nome del file e può essere quello che si desidera. In genere si sceglie una parola o una frase che riepiloga le operazioni eseguite nella migrazione. Ad esempio, è possibile denominare una migrazione successiva "AddDepartmentTable".

Se la migrazione iniziale è stata creata quando il database esisteva già, il codice di creazione del database viene generato ma non è necessario eseguirlo perché il database corrisponde già al modello di dati. Quando si distribuisce l'app in un altro ambiente in cui il database non esiste ancora, questo codice verrà eseguito per creare il database, è consigliabile quindi testarlo prima. Ecco perché è stato modificato il nome del database nella stringa di connessione precedente, in modo che le migrazioni possano crearne una nuova da zero.

  1. Nella finestra Console di Gestione pacchetti immettere il comando seguente:

    update-database

    Il update-database comando esegue il Up metodo per creare il database e quindi esegue il Seed metodo per popolare il database. Lo stesso processo verrà eseguito automaticamente nell'ambiente di produzione dopo la distribuzione dell'applicazione, come si vedrà nella sezione seguente.

  2. Usare Esplora server per esaminare il database come è stato fatto nella prima esercitazione ed eseguire l'applicazione per verificare che tutto funzioni ancora come in precedenza.

Distribuisci in Azure

Finora l'applicazione è stata eseguita localmente in IIS Express nel computer di sviluppo. Per renderlo disponibile per altri utenti da usare tramite Internet, è necessario distribuirlo a un provider di hosting Web. In questa sezione dell'esercitazione verrà distribuita in Azure. Questa sezione è facoltativa; è possibile ignorare questo e continuare con l'esercitazione seguente oppure è possibile adattare le istruzioni in questa sezione per un provider di hosting diverso a scelta.

Usare le migrazioni Code First per distribuire il database

Per distribuire il database, si userà Migrazioni Code First. Quando si crea il profilo di pubblicazione usato per configurare le impostazioni per la distribuzione da Visual Studio, si selezionerà una casella di controllo denominata Aggiorna database. Questa impostazione fa sì che il processo di distribuzione configuri automaticamente il file Web.config dell'applicazione nel server di destinazione in modo che Code First usi la MigrateDatabaseToLatestVersion classe di inizializzatore.

Visual Studio non esegue alcuna operazione con il database durante il processo di distribuzione durante la copia del progetto nel server di destinazione. Quando si esegue l'applicazione distribuita e si accede al database per la prima volta dopo la distribuzione, Code First verifica se il database corrisponde al modello di dati. Se si verifica una mancata corrispondenza, Code First crea automaticamente il database (se non esiste ancora) o aggiorna lo schema del database alla versione più recente (se esiste un database ma non corrisponde al modello). Se l'applicazione implementa un metodo Migrations Seed , il metodo viene eseguito dopo la creazione del database o l'aggiornamento dello schema.

Il metodo Migrations Seed inserisce i dati di test. Se si esegue la distribuzione in un ambiente di produzione, è necessario modificare il Seed metodo in modo che inserisca solo i dati da inserire nel database di produzione. Ad esempio, nel modello di dati corrente potrebbe essere necessario avere corsi reali, ma studenti fittizi nel database di sviluppo. È possibile scrivere un Seed metodo per caricare entrambi in fase di sviluppo e quindi impostare come commento gli studenti fittizi prima di eseguire la distribuzione nell'ambiente di produzione. In alternativa, è possibile scrivere un Seed metodo per caricare solo i corsi e immettere manualmente gli studenti fittizi nel database di test usando l'interfaccia utente dell'applicazione.

Creare un account Azure

È necessario un account Azure. Se non è già disponibile, ma si ha una sottoscrizione di Visual Studio, è possibile attivare i vantaggi della sottoscrizione. In caso contrario, è possibile creare un account di valutazione gratuito in pochi minuti. Per informazioni dettagliate, vedere Versione di valutazione gratuita di Azure.

Creare un sito Web e un database SQL in Azure

L'app Web in Azure verrà eseguita in un ambiente di hosting condiviso, ovvero viene eseguita in macchine virtuali (VM) condivise con altri client di Azure. Un ambiente di hosting condiviso è un punto di partenza economicamente conveniente per iniziare a utilizzare il cloud. In seguito, in caso di incremento del traffico Web, è possibile scalare l'applicazione in modo da soddisfare le nuove esigenze tramite l'esecuzione su macchine virtuali dedicate. Per altre informazioni sulle opzioni dei prezzi per il servizio app Azure, vedere prezzi di servizio app.

Si distribuirà il database nel database SQL di Azure. Il database SQL è un servizio di database relazionale basato sul cloud basato sulle tecnologie DI SQL Server. Strumenti e applicazioni che funzionano con SQL Server funzionano anche con il database SQL.

  1. Nel portale di gestione di Azure scegliere Crea una risorsa nella scheda a sinistra e quindi scegliere Visualizza tutto nel riquadro Nuovo (o pannello) per visualizzare tutte le risorse disponibili. Scegliere App Web e SQL nella sezione Web del pannello Tutto . Infine, scegliere Crea.

    Creare una risorsa nel portale di Azure

    Verrà aperto il modulo per creare una nuova risorsa Nuova app Web e SQL .

  2. Immettere una stringa nella casella Nome app da usare come URL univoco per l'applicazione. L'URL completo sarà costituito da ciò che si immette qui più il dominio predefinito di app Azure Services (.azurewebsites.net). Se il nome dell'app è già stato preso, la procedura guidata invia una notifica in rosso Il nome dell'app non è disponibile. Se il nome dell'app è disponibile, viene visualizzato un segno di spunta verde.

  3. Nella casella Sottoscrizione scegliere la sottoscrizione di Azure in cui si vuole che risieda il servizio app.

  4. Nella casella di testo Gruppo di risorse scegliere un gruppo di risorse o crearne uno nuovo. Questa impostazione specifica il data center in cui verrà eseguito il sito Web. Per altre informazioni sui gruppi di risorse, vedere Gruppi di risorse.

  5. Creare un nuovo piano di servizio app facendo clic sulla sezione servizio app, Crea nuovo e compilare servizio app piano (può essere lo stesso nome di servizio app), Località e Piano tariffario (è disponibile un'opzione gratuita).

  6. Fare clic su database SQL, quindi scegliere Crea un nuovo database o selezionare un database esistente.

  7. Nella casella Nome immettere un nome per il database.

  8. Fare clic sulla casella Server di destinazione e quindi selezionare Crea un nuovo server. In alternativa, se in precedenza è stato creato un server, è possibile selezionare tale server dall'elenco dei server disponibili.

  9. Scegliere La sezione Piano tariffario , scegliere Gratuito. Se sono necessarie risorse aggiuntive, è possibile aumentare le prestazioni del database in qualsiasi momento. Per altre informazioni sui prezzi di Azure SQL, vedere prezzi database SQL di Azure.

  10. Modificare le regole di confronto in base alle esigenze.

  11. Immettere un nome utente amministratore SQL e una password amministratore SQL.

    • Se è stato selezionato Nuovo server database SQL, definire un nuovo nome e una nuova password che verranno usati in un secondo momento quando si accede al database.
    • Se è stato selezionato un server creato in precedenza, immettere le credenziali per tale server.
  12. La raccolta di dati di telemetria può essere abilitata per servizio app tramite Application Insights. Con una configurazione piccola, Application Insights raccoglie informazioni preziose su eventi, eccezioni, dipendenze, richieste e traccia. Per altre informazioni su Application Insights, vedere Monitoraggio di Azure.

  13. Fare clic su Crea nella parte inferiore per indicare che è stato completato.

    Il portale di gestione torna alla pagina Dashboard e l'area Notifiche nella parte superiore della pagina mostra che il sito è in corso di creazione. Dopo un periodo di tempo (in genere inferiore a un minuto), viene visualizzata una notifica che indica che la distribuzione è riuscita. Nella barra di spostamento a sinistra il nuovo servizio app viene visualizzato nella sezione servizio app s e il nuovo database SQL viene visualizzato nella sezione Database SQL.

Distribuire l'app in Azure

  1. In Visual Studio fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Pubblica dal menu di scelta rapida.

  2. Nella pagina Selezionare una destinazione di pubblicazione scegliere servizio app e quindi Selezionare esistente e quindi scegliere Pubblica.

    Selezionare una pagina di destinazione di pubblicazione

  3. Se la sottoscrizione di Azure non è stata aggiunta in precedenza in Visual Studio, seguire questa procedura sullo schermo. Questa procedura consente a Visual Studio di connettersi alla sottoscrizione di Azure in modo che l'elenco di servizio app includa il sito Web.

  4. Nella pagina servizio app selezionare la sottoscrizione a cui è stato aggiunto il servizio app. In Visualizza selezionare Gruppo di risorse. Espandere il gruppo di risorse a cui è stato aggiunto il servizio app e quindi selezionare il servizio app. Scegliere OK per pubblicare l'app.

  5. Nella finestra Output vengono indicate le azioni di distribuzione effettuate e viene segnalato il corretto completamento della distribuzione.

  6. Al termine della distribuzione, il browser predefinito si apre automaticamente all'URL del sito Web distribuito.

    Students_index_page_with_paging

    L'app è ora in esecuzione nel cloud.

A questo punto, il database SchoolContext è stato creato nel database SQL di Azure perché è stata selezionata l'opzione Esegui Migrazioni Code First (viene eseguita all'avvio dell'app). Il file Web.config nel sito Web distribuito è stato modificato in modo che l'inizializzatore MigrateDatabaseToLatestVersion venga eseguito la prima volta che il codice legge o scrive i dati nel database (che si verifica quando è stata selezionata la scheda Students ):

Estratto file Web.config

Il processo di distribuzione ha anche creato un nuovo stringa di connessione (SchoolContext_DatabasePublish) per Migrazioni Code First da usare per aggiornare lo schema del database e il seeding del database.

Stringa di connessione nel file Web.config

È possibile trovare la versione distribuita del file Web.config nel proprio computer in ContosoUniversity\obj\Release\Package\PackageTmp\Web.config. È possibile accedere al file Web.config distribuito usando FTP. Per istruzioni, vedere ASP.NET distribuzione Web con Visual Studio: Distribuzione di un aggiornamento del codice. Seguire le istruzioni che iniziano con "Per usare uno strumento FTP, sono necessari tre elementi: l'URL FTP, il nome utente e la password".

Nota

L'app Web non implementa la sicurezza, quindi chiunque trovi l'URL può modificare i dati. Per istruzioni su come proteggere il sito Web, vedere Distribuire un'app MVC sicura ASP.NET con appartenenza, OAuth e database SQL in Azure. È possibile impedire ad altri utenti di usare il sito arrestando il servizio usando il portale di gestione di Azure o Esplora server in Visual Studio.

Arresta voce di menu del servizio app

Scenari di migrazioni avanzate

Se si distribuisce un database eseguendo automaticamente le migrazioni come illustrato in questa esercitazione e si esegue la distribuzione in un sito Web eseguito su più server, è possibile ottenere più server che tentano di eseguire migrazioni contemporaneamente. Le migrazioni sono atomiche, quindi se due server tentano di eseguire la stessa migrazione, una avrà esito positivo e l'altra avrà esito negativo (presupponendo che le operazioni non possano essere eseguite due volte). In questo scenario, se si desidera evitare questi problemi, è possibile chiamare manualmente le migrazioni e configurare il proprio codice in modo che si verifichi una sola volta. Per altre informazioni, vedere Esecuzione e scripting delle migrazioni dal codice nel blog di Rowan Miller e Migrate.exe (per l'esecuzione di migrazioni dalla riga di comando).

Per informazioni su altri scenari di migrazioni, vedere Serie screencast delle migrazioni.

Aggiornare una migrazione specifica

update-database -target MigrationName

Il update-database -target MigrationName comando esegue la migrazione di destinazione.

Ignorare le modifiche alla migrazione al database

Add-migration MigrationName -ignoreChanges

ignoreChanges crea una migrazione vuota con il modello corrente come snapshot.

Inizializzatori Code First

Nella sezione relativa alla distribuzione è stato visualizzato l'inizializzatore MigrateDatabaseToLatestVersion in uso. Code First fornisce anche altri inizializzatori, tra cui CreateDatabaseIfNotExists (impostazione predefinita), DropCreateDatabaseIfModelChanges (usato in precedenza) e DropCreateDatabaseAlways. L'inizializzatore DropCreateAlways può essere utile per configurare le condizioni per gli unit test. È anche possibile scrivere inizializzatori personalizzati ed è possibile chiamare un inizializzatore in modo esplicito se non si vuole attendere fino a quando l'applicazione non legge o scrive nel database.

Per altre informazioni sugli inizializzatori, vedere Informazioni sugli inizializzatori di database in Entity Framework Code First e nel capitolo 6 del libro Programming Entity Framework: Code First di Julie Lerman e Rowan Miller.

Ottenere il codice

Scaricare il progetto completato

Risorse aggiuntive

I collegamenti ad altre risorse di Entity Framework sono disponibili in ASP.NET Accesso ai dati - Risorse consigliate.

Passaggi successivi

In questa esercitazione:

  • Migrazioni Code First abilitate
  • Distribuzione dell'app in Azure (facoltativo)

Passare all'articolo successivo per informazioni su come creare un modello di dati più complesso per un'applicazione MVC ASP.NET.