Share via


Creazione di un modello di dati entity Framework per un'applicazione MVC di ASP.NET (1 di 10)

di Tom Dykstra

Nota

È disponibile una versione più recente di questa serie di esercitazioni per Visual Studio 2013, Entity Framework 6 e MVC 5.

L'applicazione Web di esempio Contoso University illustra come creare applicazioni ASP.NET MVC 4 usando Entity Framework 5 e Visual Studio 2012. L'applicazione di esempio è un sito Web per una fittizia Contoso University. Include funzionalità, come ad esempio l'ammissione di studenti, la creazione di corsi e le assegnazioni di insegnati. Questa serie di esercitazioni illustra come compilare l'applicazione di esempio Contoso University.

Code First

Esistono tre modi per usare i dati in Entity Framework: Database First, Model First e Code First. Questa esercitazione è per Code First. Per informazioni sulle differenze tra questi flussi di lavoro e indicazioni su come scegliere la soluzione migliore per lo scenario, vedere Flussi di lavoro di sviluppo di Entity Framework.

MVC

L'applicazione di esempio è basata su ASP.NET MVC. Se si preferisce usare il modello di Web Forms ASP.NET, vedere la serie di esercitazioni Di associazione di modelli e Web Forms e ASP.NETmappa del contenuto di accesso ai dati.

Versioni software

Illustrato nell'esercitazione Funziona anche con
Windows 8 Windows 7
Visual Studio 2012 Visual Studio 2012 Express for Web. Questa operazione viene installata automaticamente da Windows Azure SDK se non si ha già VS 2012 o VS 2012 Express for Web. Visual Studio 2013 dovrebbe funzionare, ma l'esercitazione non è stata testata con essa e alcune selezioni di menu e finestre di dialogo sono diverse. La versione di VS 2013 di Windows Azure SDK è necessaria per la distribuzione di Windows Azure.
.NET 4.5 La maggior parte delle funzionalità visualizzate funzionerà in .NET 4, ma alcuni non funzioneranno. Ad esempio, il supporto dell'enumerazione in EF richiede .NET 4.5.
Entity Framework 5
Windows Azure SDK 2.1 Se si ignorano i passaggi di distribuzione di Windows Azure, non è necessario l'SDK. Quando viene rilasciata una nuova versione dell'SDK, il collegamento installerà la versione più recente. In questo caso, potrebbe essere necessario adattare alcune delle istruzioni alle nuove funzionalità e interfaccia utente.

Domande

Se si hanno domande che non sono direttamente correlate all'esercitazione, è possibile pubblicarli nel forum ASP.NET Entity Framework, nel forum entity Framework e LINQ to Entities o StackOverflow.com.

Ringraziamenti

Vedere l'ultima esercitazione nella serie per i riconoscimenti e una nota su VB.

Applicazione Web Contoso University

L'applicazione che sarà compilata in queste esercitazioni è un semplice sito Web universitario.

Gli utenti possono visualizzare e aggiornare le informazioni che riguardano studenti, corsi e insegnanti. Di seguito sono disponibili alcune schermate che saranno create.

Students_Index_page

Screenshot che mostrano la pagina di ricerca Studenti dell'applicazione Web Contoso University di esempio e la pagina Crea nuovo studente.

Lo stile dell'interfaccia utente del sito è simile a quanto è stato generato tramite i modelli predefiniti. L'esercitazione si concentra pertanto soprattutto sull'uso di Entity Framework.

Prerequisiti

Le istruzioni e le schermate in questa esercitazione presuppongono che si usi Visual Studio 2012 o Visual Studio 2012 Express for Web, con l'aggiornamento più recente e Azure SDK per .NET installato a partire da luglio 2013. È possibile ottenere tutto questo con il collegamento seguente:

Azure SDK per .NET (Visual Studio 2012)

Se Visual Studio è installato, il collegamento precedente installerà tutti i componenti mancanti. Se Visual Studio non è disponibile, il collegamento installerà Visual Studio 2012 Express for Web. È possibile usare Visual Studio 2013, ma alcune delle procedure e delle schermate necessarie saranno diverse.

Creare un'applicazione Web MVC

Aprire Visual Studio e creare un nuovo progetto C# denominato "ContosoUniversity" usando il modello di applicazione Web MVC 4 ASP.NET MVC 4 . Assicurarsi di avere come destinazione .NET Framework 4.5 (si useranno enum le proprietà e che richiedono .NET 4.5).

New_project_dialog_box

Nella finestra di dialogo Nuovo ASP.NET progetto MVC 4 selezionare il modello applicazione Internet .

Lasciare selezionato il motore di visualizzazione Razor e lasciare deselezionata la casella di controllo Crea un progetto di unit test .

Fare clic su OK.

Project_template_options

Configurare lo stile del sito

Con alcune modifiche è possibile impostare il menu del sito, il layout e la home page.

Aprire Views\Shared\_Layout.cshtml e sostituire il contenuto del file con il codice seguente. Le modifiche sono evidenziate.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - Contoso University</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body>
        <header>
            <div class="content-wrapper">
                <div class="float-left">
                    <p class="site-title">@Html.ActionLink("Contoso University", "Index", "Home")</p>
                </div>
                <div class="float-right">
                    <section id="login">
                        @Html.Partial("_LoginPartial")
                    </section>
                    <nav>
                        <ul id="menu">
                            <li>@Html.ActionLink("Home", "Index", "Home")</li>
                            <li>@Html.ActionLink("About", "About", "Home")</li>
                            <li>@Html.ActionLink("Students", "Index", "Student")</li>
                            <li>@Html.ActionLink("Courses", "Index", "Course")</li>
                            <li>@Html.ActionLink("Instructors", "Index", "Instructor")</li>
                            <li>@Html.ActionLink("Departments", "Index", "Department")</li>
                        </ul>
                    </nav>
                </div>
            </div>
        </header>
        <div id="body">
            @RenderSection("featured", required: false)
            <section class="content-wrapper main-content clear-fix">
                @RenderBody()
            </section>
        </div>
        <footer>
            <div class="content-wrapper">
                <div class="float-left">
                    <p>&copy; @DateTime.Now.Year - Contoso University</p>
                </div>
            </div>
        </footer>

        @Scripts.Render("~/bundles/jquery")
        @RenderSection("scripts", required: false)
    </body>
</html>

Questo codice apporta le modifiche seguenti:

  • Sostituisce le istanze del modello di "My ASP.NET MVC Application" e "your logo here" con "Contoso University".
  • Aggiunge diversi collegamenti di azione che verranno usati più avanti nell'esercitazione.

In Views\Home\Index.cshtml sostituire il contenuto del file con il codice seguente per eliminare i paragrafi del modello relativi a ASP.NET e MVC:

@{
    ViewBag.Title = "Home Page";
}
@section featured {
    <section class="featured">
        <div class="content-wrapper">
            <hgroup class="title">
                <h1>@ViewBag.Title.</h1>
                <h2>@ViewBag.Message</h2>
            </hgroup>
        </div>
    </section>
}

In Controller\HomeController.cs modificare il valore per ViewBag.Message nel metodo Action in "Welcome to Contoso University!", come illustrato nell'esempio Index seguente:

public ActionResult Index()
{
    ViewBag.Message = "Welcome to Contoso University";

    return View();
}

Premere CTRL+F5 per eseguire il sito. Viene visualizzata la home page con il menu principale.

Contoso_University_home_page

Creare il modello di dati

A questo punto è possibile creare le classi delle entità per l'applicazione di Contoso University. Si inizierà con le tre entità seguenti:

Class_diagram

Esiste una relazione uno-a-molti tra le entità Student e Enrollment ed esiste una relazione uno-a-molti tra le entità Course e Enrollment. In altre parole, uno studente può iscriversi a un numero qualsiasi di corsi e un corso può avere un numero qualsiasi di studenti iscritti.

Nelle sezioni seguenti viene creata una classe per ognuna di queste entità.

Nota

Se si tenta di compilare il progetto prima di completare la creazione di tutte queste classi di entità, si otterranno errori del compilatore.

Entità studente

Student_entity

Nella cartella Modelli creare Student.cs e sostituire il codice esistente con il codice seguente:

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int StudentID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }
        
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
}

La proprietà StudentID diventa la colonna di chiave primaria della tabella di database che corrisponde a questa classe. Per impostazione predefinita, Entity Framework interpreta una proprietà denominata o nome IDclasseID come chiave primaria.

La proprietà Enrollments rappresenta una proprietà di navigazione. Le proprietà di navigazione contengono altre entità correlate a questa entità. In questo caso, la Enrollments proprietà di un'entità Student conterrà tutte le Enrollment entità correlate a tale Student entità. In altre parole, se una Student determinata riga nel database ha due righe correlate Enrollment (righe che contengono il valore della chiave primaria dello studente nella StudentID colonna chiave esterna), la Student proprietà di spostamento dell'entità Enrollments conterrà queste due Enrollment entità.

Le proprietà di spostamento vengono in genere definite in virtual modo che possano sfruttare determinate funzionalità di Entity Framework, ad esempio il caricamento lazy. Il caricamento lazy verrà spiegato più avanti nell'esercitazione Lettura dei dati correlati più avanti in questa serie.

Se una proprietà di navigazione può contenere più entità (come nel caso di relazioni molti-a-molti e uno-a-molti), il tipo della proprietà deve essere un elenco in cui le voci possono essere aggiunte, eliminate e aggiornate, come ad esempio ICollection.

Entità registrazione

Enrollment_entity

Nella cartella Models creare Enrollment.cs e sostituire il codice esistente con il codice seguente:

namespace ContosoUniversity.Models
{
    public enum Grade
    {
        A, B, C, D, F
    }

    public class Enrollment
    {
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }
        public Grade? Grade { get; set; }
        
        public virtual Course Course { get; set; }
        public virtual Student Student { get; set; }
    }
}

La proprietà Grade è un'enumerazione. Il punto interrogativo dopo la dichiarazione del tipo Grade indica che la proprietà Gradeammette i valori Null. Un grado null è diverso da un livello zero: null significa che un grado non è noto o non è ancora stato assegnato.

La proprietà StudentID è una chiave esterna e la proprietà di navigazione corrispondente è Student. Un'entità Enrollment è associata a un'entità Student, pertanto la proprietà può contenere un'unica entità Student, a differenza della proprietà di navigazione Student.Enrollments vista in precedenza, che può contenere più entità Enrollment.

La proprietà CourseID è una chiave esterna e la proprietà di navigazione corrispondente è Course. Un'entità Enrollment è associata a un'entità Course.

Entità Course

Course_entity

Nella cartella Modelli creare Course.cs sostituendo il codice esistente con il codice seguente:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Course
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }
        
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
}

La proprietà Enrollments rappresenta una proprietà di navigazione. È possibile correlare un'entità Course a un numero qualsiasi di entità Enrollment.

Verranno fornite altre informazioni su [DatabaseGenerated(DatabaseGeneratedOption). Attributo None)] nell'esercitazione successiva. In pratica, questo attributo consente di immettere la chiave primaria per il corso invece di essere generata dal database.

Creare il contesto di database

La classe principale che coordina la funzionalità di Entity Framework per un determinato modello di dati è la classe di contesto del database . Questa classe viene creata derivando dalla classe System.Data.Entity.DbContext . Nel codice vengono specificate le entità incluse nel modello di dati. È anche possibile personalizzare un determinato comportamento di Entity Framework. In questo progetto la classe è denominata SchoolContext.

Creare una cartella denominata DAL (per Livello di accesso ai dati). In tale cartella creare un nuovo file di classe denominato SchoolContext.cs e sostituire il codice esistente con il codice seguente:

using ContosoUniversity.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace ContosoUniversity.DAL
{
    public class SchoolContext : DbContext
    {
        public DbSet<Student> Students { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Course> Courses { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }
}

Questo codice crea una proprietà DbSet per ogni set di entità. Nella terminologia di Entity Framework un set di entità corrisponde in genere a una tabella di database e un'entità corrisponde a una riga nella tabella.

L'istruzione modelBuilder.Conventions.Remove nel metodo OnModelCreating impedisce che i nomi di tabella vengano pluralizzati. Se non è stata eseguita questa operazione, le tabelle generate verranno denominate Students, Coursese Enrollments. Invece, i nomi delle tabelle saranno Student, Coursee Enrollment. Gli sviluppatori non hanno un'opinione unanime sul fatto che i nomi di tabella debbano essere pluralizzati oppure no. Questa esercitazione usa il modulo singolare, ma il punto importante è che è possibile selezionare il modulo preferito includendo o omettendo questa riga di codice.

SQL Server Express LocalDB

LocalDB è una versione leggera del motore di database di SQL Server Express che avvia su richiesta ed esegue in modalità utente. LocalDB viene eseguito in una modalità di esecuzione speciale di SQL Server Express che consente di usare i database come file di .mdf. In genere, i file di database LocalDB vengono mantenuti nella cartella App_Data di un progetto Web. La funzionalità dell'istanza utente in SQL Server Express consente anche di usare i file di .mdf, ma la funzionalità dell'istanza utente è deprecata. Pertanto, LocalDB è consigliabile usare i file .mdf.

In genere SQL Server Express non viene usato per le applicazioni Web di produzione. LocalDB in particolare non è consigliato per l'uso di produzione con un'applicazione Web perché non è progettato per l'uso con IIS.

In Visual Studio 2012 e versioni successive, LocalDB viene installato per impostazione predefinita con Visual Studio. In Visual Studio 2010 e versioni precedenti, SQL Server Express (senza LocalDB) viene installato per impostazione predefinita con Visual Studio. Se si usa Visual Studio 2010, è necessario installarlo manualmente.

In questa esercitazione si userà LocalDB in modo che il database possa essere archiviato nella cartella App_Data come file di .mdf. Aprire il file radiceWeb.confige aggiungere una nuova stringa di connessione alla raccolta, come illustrato nell'esempio connectionStrings seguente. Assicurarsi di aggiornare il file diWeb.config nella cartella del progetto radice. È disponibile anche un file Web.config nella sottocartella Visualizzazioni che non è necessario aggiornare.

<add name="SchoolContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ContosoUniversity;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\ContosoUniversity.mdf" providerName="System.Data.SqlClient" />

Per impostazione predefinita, Entity Framework cerca un stringa di connessione denominato uguale DbContext alla classe (SchoolContext per questo progetto). Il stringa di connessione aggiunto specifica un database LocalDB denominato ContosoUniversity.mdf situato nella cartella App_Data. Per altre informazioni, vedere SQL Server stringhe di connessione per applicazioni Web ASP.NET.

Non è effettivamente necessario specificare il stringa di connessione. Se non si specifica un stringa di connessione, Entity Framework creerà uno per l'utente. Tuttavia, il database potrebbe non trovarsi nella cartella App_data dell'app. Per informazioni sulla posizione in cui verrà creato il database, vedere Code First to a New Database .For information on where the database will be create, see Code First to a New Database.

La connectionStrings raccolta include anche un stringa di connessione denominato DefaultConnection che viene usato per il database di appartenenza. Non si usa il database di appartenenza in questa esercitazione. L'unica differenza tra le due stringhe di connessione è il nome del database e il valore dell'attributo name.

Configurare ed eseguire una prima migrazione del codice

Quando si inizia a sviluppare un'applicazione, il modello di dati cambia frequentemente e ogni volta che il modello cambia la sincronizzazione con il database. È possibile configurare Entity Framework per eliminare e ricreare automaticamente il database ogni volta che si modifica il modello di dati. Questo non è un problema all'inizio dello sviluppo perché i dati di test vengono facilmente creati, ma dopo aver distribuito in produzione si vuole in genere aggiornare lo schema del database senza eliminare il database. La funzionalità Migrazione consente a Code First di aggiornare il database senza eliminarlo e ricrearlo. All'inizio del ciclo di sviluppo di un nuovo progetto, è possibile usare DropCreateDatabaseIfModelChanges per eliminare, ricreare e ri-inizializzare il database ogni volta che il modello cambia. Si è pronti per distribuire l'applicazione, è possibile convertire nell'approccio delle migrazioni. Per questa esercitazione si useranno solo le migrazioni. Per altre informazioni, vedere Migrazioni Code First e serie screencast delle migrazioni.

Abilitare Migrazioni Code First

  1. Dal menu Strumenti fare clic su Gestione pacchetti NuGet e quindi console di Gestione pacchetti.

    Selecting_Package_Manager_Console

  2. Al prompt immettere il PM> comando seguente:

    enable-migrations -contexttypename SchoolContext
    

    comando enable-migrations

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

    Cartella Migrazioni

    La Configuration classe include un Seed metodo chiamato quando il database viene creato e ogni volta che viene aggiornato dopo una modifica del modello di dati.

    internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.Models.SchoolContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }
    
        protected override void Seed(ContosoUniversity.Models.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 di questo Seed metodo consiste nell'inserire i dati di test nel database dopo che Code First lo crea o lo aggiorna.

Configurare il metodo seed

Il metodo Seed viene eseguito quando Migrazioni Code First crea il database e ogni volta che aggiorna il database alla migrazione più recente. Lo scopo del metodo Seed consiste nell'inserire i dati nelle tabelle prima che l'applicazione acceda al database per la prima volta.

Nelle versioni precedenti di Code First, prima che le migrazioni siano state rilasciate, è stato comune Seed inserire i dati di test, perché con ogni modifica del modello durante lo sviluppo il database deve essere completamente eliminato e ricreato da zero. Con Migrazioni Code First, i dati di test vengono mantenuti dopo le modifiche del database, quindi i dati di test nel metodo Seed non sono in genere necessari. In effetti, non si vuole che il metodo inserisca i dati di test se si useranno Le migrazioni per distribuire il Seed database in produzione, perché il Seed metodo verrà eseguito in produzione. In tal caso si vuole che il Seed metodo inserisca nel database solo i dati da inserire nell'ambiente di produzione. Ad esempio, è possibile che il database includa nomi di reparto effettivi nella Department tabella quando l'applicazione diventa disponibile in produzione.

Per questa esercitazione si useranno Migrazioni per la distribuzione, ma il Seed metodo inserisce 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 caricherà i dati di test nel nuovo database.

    namespace ContosoUniversity.Migrations
    {
       using System;
       using System.Collections.Generic;
       using System.Data.Entity.Migrations;
       using System.Linq;
       using ContosoUniversity.Models;
    
       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").StudentID, 
                        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID, 
                        Grade = Grade.A 
                    },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").StudentID,
                        CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID, 
                        Grade = Grade.C 
                     },                            
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").StudentID,
                        CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID, 
                        Grade = Grade.B
                     },
                     new Enrollment { 
                         StudentID = students.Single(s => s.LastName == "Alonso").StudentID,
                        CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment { 
                         StudentID = students.Single(s => s.LastName == "Alonso").StudentID,
                        CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment {
                        StudentID = students.Single(s => s.LastName == "Alonso").StudentID,
                        CourseID = courses.Single(c => c.Title == "Composition" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Anand").StudentID,
                        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Anand").StudentID,
                        CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
                        Grade = Grade.B         
                     },
                    new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Barzdukas").StudentID,
                        CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
                        Grade = Grade.B         
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Li").StudentID,
                        CourseID = courses.Single(c => c.Title == "Composition").CourseID,
                        Grade = Grade.B         
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Justice").StudentID,
                        CourseID = courses.Single(c => c.Title == "Literature").CourseID,
                        Grade = Grade.B         
                     }
                };
    
             foreach (Enrollment e in enrollments)
             {
                var enrollmentInDataBase = context.Enrollments.Where(
                    s =>
                         s.Student.StudentID == e.StudentID &&
                         s.Course.CourseID == e.CourseID).SingleOrDefault();
                if (enrollmentInDataBase == null)
                {
                   context.Enrollments.Add(e);
                }
             }
             context.SaveChanges();
          }
       }
    }
    

    Il metodo Seed accetta l'oggetto contesto del 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 al 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 i dati usano il metodo AddOrUpdate per eseguire un'operazione "upsert". Poiché il Seed metodo viene eseguito con 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 delle modifiche apportate ai dati che potrebbero essere state apportate 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 delle modifiche che si desidera che le modifiche rimangano dopo gli aggiornamenti del database. In questo 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 usare per verificare se esiste già una riga. Per i dati degli studenti di test specificati, la LastName proprietà può essere usata per questo scopo poiché ogni cognome nell'elenco è univoco:

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

    Questo codice presuppone che gli ultimi nomi 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 altre informazioni sul metodo, vedere Prendere cura del metodo EF 4.3 AddOrUpdate nel blog di Julie Lerman.AddOrUpdate

    Il codice che aggiunge Enrollment entità non usa il AddOrUpdate metodo . Verifica se esiste già un'entità e inserisce l'entità se non esiste. Questo approccio mantiene le modifiche apportate a un livello di registrazione durante l'esecuzione delle migrazioni. Il codice scorre attraverso ogni membro dell'elencoEnrollment 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 aggiungerà ogni registrazione.

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

    Per informazioni su come eseguire il debug del Seed metodo e su come gestire i dati ridondanti, ad esempio due studenti denominati "Alexander Carson", vedere Seeding and Debug Entity Framework (EF) nel blog di Rick Anderson.

  2. Compilare il progetto.

Creare ed eseguire la prima migrazione

  1. Nella finestra Console di Gestione pacchetti immettere i comandi seguenti:

    add-migration InitialCreate
    update-database
    

    Screenshot che mostra la finestra Console di Gestione pacchetti. I comandi aggiungono il carattere di sottolineatura di sottolineatura Creazione iniziale e aggiornamento del database trattino sono evidenziati.

    Il add-migration comando aggiunge alla cartella Migrations un file [DateStamp]_InitialCreate.cs che contiene il codice che crea il database. Il primo parametro (InitialCreate) viene usato per il nome del file e può essere qualsiasi elemento desiderato; in genere si sceglie una parola o una frase che riepiloga le operazioni eseguite nella migrazione. Ad esempio, è possibile denominare una migrazione successiva "AddDepartmentTable".

    Cartella Migrations con migrazione iniziale

    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. 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. Il codice seguente mostra il contenuto del InitialCreate file:

    namespace ContosoUniversity.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;
        
        public partial class InitialCreate : DbMigration
        {
            public override void Up()
            {
                CreateTable(
                    "dbo.Student",
                    c => new
                        {
                            StudentID = c.Int(nullable: false, identity: true),
                            LastName = c.String(),
                            FirstMidName = c.String(),
                            EnrollmentDate = c.DateTime(nullable: false),
                        })
                    .PrimaryKey(t => t.StudentID);
                
                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.Course",
                    c => new
                        {
                            CourseID = c.Int(nullable: false),
                            Title = c.String(),
                            Credits = c.Int(nullable: false),
                        })
                    .PrimaryKey(t => t.CourseID);
                
            }
            
            public override void Down()
            {
                DropIndex("dbo.Enrollment", new[] { "StudentID" });
                DropIndex("dbo.Enrollment", new[] { "CourseID" });
                DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student");
                DropForeignKey("dbo.Enrollment", "CourseID", "dbo.Course");
                DropTable("dbo.Course");
                DropTable("dbo.Enrollment");
                DropTable("dbo.Student");
            }
        }
    }
    

    Il update-database comando esegue il Up metodo per creare il database e quindi esegue il Seed metodo per popolare il database.

È stato creato un database SQL Server per il modello di dati. Il nome del database è ContosoUniversity e il file .mdf si trova nella cartella App_Data del progetto, perché questo è quello specificato nel stringa di connessione.

È possibile usare Esplora server o SQL Server Esplora oggetti (SSOX) per visualizzare il database in Visual Studio. Per questa esercitazione si userà Esplora server. In Visual Studio Express 2012 per Il Web, Esplora server è denominato Esplora database.

  1. Scegliere Esplora server dal menu Visualizza.

  2. Fare clic sull'icona Aggiungi connessione .

    Screenshot che mostra la finestra Esplora database. L'icona Aggiungi connessione è evidenziata.

  3. Se viene visualizzata la finestra di dialogo Scegli origine dati, fare clic su Microsoft SQL Server e quindi fare clic su Continua.

    Screenshot che mostra la finestra di dialogo Scegli origine dati. È selezionata l'origine dati Microsoft S Q L Server.

  4. Nella finestra di dialogo Aggiungi connessione immettere (localdb)\v11.0 come Nome server. In Selezionare o immettere un nome di database selezionare ContosoUniversity.

    Screenshot che mostra la finestra di dialogo Aggiungi connessione. Il nome del server di esempio e il database Contoso University sono evidenziati.

  5. Scegliere OK.

  6. Espandere SchoolContext e quindi tabelle.

    Screenshot che mostra la pagina Esplora server. Le schede Contesto dell'istituto di istruzione e Tabelle vengono espanse.

  7. Fare clic con il pulsante destro del mouse sulla tabella Student e scegliere Mostra dati tabella per visualizzare le colonne create e le righe inserite nella tabella.

    Tabella Student

Creazione di un controller e visualizzazioni per studenti

Il passaggio successivo consiste nel creare un controller e viste MVC ASP.NET nell'applicazione che possono essere usati con una di queste tabelle.

  1. Per creare un Student controller, fare clic con il pulsante destro del mouse sulla cartella Controller in Esplora soluzioni, scegliere Aggiungi e quindi fare clic su Controller. Nella finestra di dialogo Aggiungi controller effettuare le selezioni seguenti e quindi fare clic su Aggiungi:

    • Nome controller: StudentController.

    • Modello: controller MVC con azioni e viste di lettura/scrittura, usando Entity Framework.

    • Classe modello: Student (ContosoUniversity.Models). Se questa opzione non viene visualizzata nell'elenco a discesa, compilare il progetto e riprovare.

    • Classe contesto dati: SchoolContext (ContosoUniversity.Models).

    • Views: Razor (CSHTML). Impostazione predefinita.

      Add_Controller_dialog_box_for_Student_controller

  2. Visual Studio apre il file Controllers\StudentController.cs . Viene visualizzata la creazione di una variabile di classe che crea un'istanza di un oggetto contesto di database:

    private SchoolContext db = new SchoolContext();
    

    Il Index metodo di azione ottiene un elenco di studenti dal set di entità Students leggendo la Students proprietà dell'istanza del contesto di database:

    public ViewResult Index()
    {
        return View(db.Students.ToList());
    }
    

    La visualizzazione Student\Index.cshtml visualizza questo elenco in una tabella:

    <table>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.LastName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.FirstMidName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.EnrollmentDate)
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstMidName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.StudentID }) |
                @Html.ActionLink("Details", "Details", new { id=item.StudentID }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.StudentID })
            </td>
        </tr>
    }
    
  3. Premere CTRL+F5 per eseguire il progetto.

    Fare clic sulla scheda Students (Studenti) per visualizzare i dati di test inseriti dal Seed metodo.

    Pagina Indice degli studenti

Convenzioni

La quantità di codice che è necessario scrivere affinché Entity Framework sia in grado di creare un database completo è minimo a causa dell'uso di convenzioni o presupposti creati da Entity Framework. Alcuni di essi sono già stati annotati:

  • Le forme pluralizzate di nomi di classi di entità vengono usate come nomi di tabella.
  • I nomi della proprietà di entità vengono usati come nomi di colonna.
  • Le proprietà di entità denominate ID o classnameID vengono riconosciute come proprietà della chiave primaria.

Si è visto che è possibile eseguire l'override delle convenzioni(ad esempio, è stato specificato che i nomi di tabella non devono essere pluralizzati) e si apprenderà come eseguire l'override delle convenzioni nell'esercitazione Creazione di un modello di dati più complesso più avanti in questa serie. Per altre informazioni, vedere Code First Conventions.

Riepilogo

È stata creata una semplice applicazione che usa Entity Framework e SQL Server Express per archiviare e visualizzare i dati. Nell'esercitazione seguente si apprenderà come eseguire operazioni CRUD di base (creazione, lettura, aggiornamento, eliminazione). È possibile lasciare commenti e suggerimenti nella parte inferiore di questa pagina. Fateci sapere come è piaciuta questa parte dell'esercitazione e come potremmo migliorarla.

I collegamenti ad altre risorse di Entity Framework sono disponibili nella mappa del contenuto ASP.NET accesso ai dati.