Condividi tramite


Creazione di un modello di dati entity Framework per un'applicazione MVC 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 ASP.NET applicazioni 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 riguarda Code First. Per informazioni sulle differenze tra questi flussi di lavoro e indicazioni su come scegliere quella 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 sull'associazione di modelli e web form e ASP.NET mappa 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 vs 2012 o VS 2012 Express for Web non è già disponibile. 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 vs 2013 di Windows Azure SDK è necessaria per la distribuzione di Windows Azure.
.NET 4.5 La maggior parte delle funzionalità mostrate funzionerà in .NET 4, ma alcuni non funzioneranno. Ad esempio, il supporto delle enumerazioni 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 tal caso, potrebbe essere necessario adattare alcune delle istruzioni alle nuove funzionalità e all'interfaccia utente.

Domande

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

Riconoscimenti

Vedere l'ultima esercitazione della 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 di 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à eventuali 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 sono 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. Assicurarsi di usare .NET Framework 4.5 come destinazione (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 selezionata l'opzione 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 Controllers\HomeController.cs modificare il valore di ViewBag.Message nel Index metodo Action in "Welcome to Contoso University!", come illustrato nell'esempio 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à Student

Student_entity

Nella cartella Models 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 ID o classname ID 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 determinata Student riga nel database ha due righe correlate Enrollment (righe che contengono il valore della chiave primaria dello studente nella colonna StudentID chiave esterna), la Student proprietà di navigazione dell'entità Enrollments conterrà queste due Enrollment entità.

Le proprietà di navigazione vengono in genere definite in virtual modo che possano sfruttare determinate funzionalità di Entity Framework, ad esempio il caricamento differita. (Il caricamento differita verrà spiegato più avanti, nel Esercitazione sulla 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à di 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 grado 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 Models 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. Per creare questa classe, derivare 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 delle tabelle vengano pluralizzati. In caso contrario, le tabelle generate verranno denominate Students, Coursese Enrollments. I nomi delle tabelle saranno Studentinvece , 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 formato singolare, ma il punto importante è che è possibile selezionare qualsiasi modulo preferito includendo o omettendo questa riga di codice.

SQL Server Express LocalDB

LocalDB è una versione leggera dell'motore di database di SQL Server Express che viene avviata su richiesta ed eseguita in modalità utente. LocalDB viene eseguito in una modalità di esecuzione speciale di SQL Server Express che consente di usare i database come file .mdf . In genere, i file di database LocalDB vengono conservati 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 consigliabile usare LocalDB per l'uso di 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 funzionare 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; è necessario installarlo manualmente se si usa Visual Studio 2010.

In questa esercitazione si userà LocalDB in modo che il database possa essere archiviato nella cartella App_Data come file .mdf. Aprire il file Web.config radice e aggiungere un nuovo stringa di connessione alla connectionStrings raccolta, come illustrato nell'esempio seguente. Assicurarsi di aggiornare File Web.config nella cartella del progetto radice. Esiste anche un file Web.config nella sottocartella Views 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 alla DbContext classe (SchoolContext per questo progetto). Il stringa di connessione aggiunto specifica un database LocalDB denominato ContosoUniversity.mdf che si trova nella cartella App_Data. Per altre informazioni, vedere Stringhe di connessione di SQL Server per ASP.NET applicazioni Web.

Non è effettivamente necessario specificare il stringa di connessione. Se non si specifica un stringa di connessione, Entity Framework ne creerà uno automaticamente. 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 in un nuovo database.

La connectionStrings raccolta include anche un stringa di connessione denominato DefaultConnection che viene usato per il database di appartenenza. In questa esercitazione non verrà usato il database di appartenenza. L'unica differenza tra i due stringa di connessione è il nome del database e il valore dell'attributo name.

Configurare ed eseguire una migrazione Code First

Quando si inizia a sviluppare un'applicazione, il modello di dati cambia frequentemente e ogni volta che il modello lo modifica non viene sincronizzato 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 ricreati, ma dopo la distribuzione nell'ambiente di produzione si vuole in genere aggiornare lo schema del database senza eliminare il database. La funzionalità Migrazioni consente a Code First di aggiornare il database senza eliminarlo e crearlo nuovamente. All'inizio del ciclo di sviluppo di un nuovo progetto, è possibile usare DropCreateDatabaseIfModelChanges per eliminare, ricreare e ripetere il seeding del database ogni volta che il modello cambia. Si è pronti per distribuire l'applicazione, è possibile eseguire la conversione nell'approccio alle 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. Nel menu Strumenti fare clic su Gestione pacchetti NuGet e quindi su Console di Gestione pacchetti.

    Selecting_Package_Manager_Console

  2. PM> Al prompt immettere il 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 viene creato il database e ogni volta che viene aggiornato dopo una modifica di un 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 è consentire di inserire 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 è consentire di inserire dati nelle tabelle prima che l'applicazione acceda al database per la prima volta.

Nelle versioni precedenti di Code First, prima del rilascio delle migrazioni, era comune per Seed i metodi inserire dati di test, perché con ogni modifica del modello durante lo sviluppo il database doveva essere completamente eliminato e ricreato da zero. 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 desidera che il Seed metodo venga inserito nel database solo i dati che si desidera inserire 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 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 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 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 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 altre informazioni sul AddOrUpdate metodo, vedere Prendersi cura del metodo AddOrUpdate di EF 4.3 nel blog di Julie Lerman.

    Il codice che aggiunge Enrollment 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 durante l'esecuzione delle migrazioni. 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.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 dati ridondanti, ad esempio due studenti denominati "Alexander Carson", vedere Seeding and Debugging Entity Framework (EF) DBs (EF) nel blog di Rick Anderson.

  2. Compilare il progetto.

Creare ed eseguire la prima migrazione

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

    add-migration InitialCreate
    update-database
    

    Screenshot che mostra la finestra della 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 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".

    Cartella Migrazioni 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 illustra 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 di SQL Server per il modello di dati. Il nome del database è ContosoUniversity e il file di .mdf si trova nella cartella di 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 su Continua.

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

  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. Fare clic su 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 in grado di usare 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 visualizzazioni 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 per l'utente è minimo a causa dell'uso di convenzioni o presupposti che Entity Framework crea. Alcuni di essi sono già stati annotati:

  • Le forme pluralizzate dei nomi delle 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 classname ID 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 verranno fornite altre informazioni sulle convenzioni e su come eseguirne l'override nell'esercitazione Creazione di un modello di dati più complesso più avanti in questa serie. Per altre informazioni, vedere Code First Conventions.For more information, see 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. Per favore, comunicaci come ti è piaciuta questa parte dell'esercitazione e come potremmo migliorarla.

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