Freigeben über


Erstellen eines Entity Framework-Datenmodells für eine ASP.NET MVC-Anwendung (1 von 10)

von Tom Dykstra

Hinweis

Eine neuere Version dieser Tutorialreihe ist für Visual Studio 2013, Entity Framework 6 und MVC 5 verfügbar.

Die Contoso University-Beispielwebanwendung veranschaulicht, wie sie ASP.NET MVC 4-Anwendungen mithilfe von Entity Framework 5 und Visual Studio 2012 erstellen. Bei der Beispiel-App handelt es sich um eine Website für die fiktive Contoso University. Sie enthält Funktionen wie die Zulassung von Studenten, die Erstellung von Kursen und Aufgaben von Dozenten. In dieser Tutorialreihe wird erläutert, wie Sie die Contoso University-Beispielanwendung erstellen.

Code First

Es gibt drei Möglichkeiten, wie Sie mit Daten in Entity Framework arbeiten können: Database First, Model First und Code First. Dieses Tutorial gilt für Code First. Informationen zu den Unterschieden zwischen diesen Workflows und anleitungen zur Auswahl des besten Workflows für Ihr Szenario finden Sie unter Entity Framework Development Workflows.

MVC

Die Beispielanwendung basiert auf ASP.NET MVC. Wenn Sie lieber mit dem ASP.NET Web Forms-Modell arbeiten möchten, lesen Sie die Tutorialreihe Modellbindung und Web Forms und ASP.NET Inhaltszuordnung für den Datenzugriff.

Softwareversionen

Im Tutorial gezeigt Funktioniert auch mit
Windows 8 Windows 7
Visual Studio 2012 Visual Studio 2012 Express für Web. Dies wird automatisch vom Windows Azure SDK installiert, wenn Sie noch nicht über VS 2012 oder VS 2012 Express für Web verfügen. Visual Studio 2013 sollte funktionieren, aber das Tutorial wurde nicht damit getestet, und einige Menüauswahlen und Dialogfelder sind unterschiedlich. Die VS 2013-Version des Windows Azure SDK ist für die Windows Azure-Bereitstellung erforderlich.
.NET 4.5 Die meisten der angezeigten Features funktionieren in .NET 4, einige jedoch nicht. Beispielsweise erfordert die Enumerationsunterstützung in EF .NET 4.5.
Entity Framework 5
Windows Azure SDK 2.1 Wenn Sie die Windows Azure-Bereitstellungsschritte überspringen, benötigen Sie das SDK nicht. Wenn eine neue Version des SDK veröffentlicht wird, wird über den Link die neuere Version installiert. In diesem Fall müssen Sie möglicherweise einige der Anweisungen an neue Benutzeroberfläche und Features anpassen.

Fragen

Wenn Sie Fragen haben, die sich nicht direkt auf das Tutorial beziehen, können Sie diese im ASP.NET Entity Framework-Forum, im Entity Framework- und LINQ to Entities-Forum oder StackOverflow.com veröffentlichen.

Danksagungen

Im letzten Tutorial der Reihe finden Sie Bestätigungen und einen Hinweis zu VB.

Die Contoso University-Webanwendung

Bei der Anwendung, die Sie mithilfe dieser Tutorials erstellen, handelt es sich um eine einfache Universitätswebsite.

Benutzer können Informationen zu den Studenten, Kursen und Dozenten abrufen. Nachfolgend werden einige Anzeigen dargestellt, die erstellt werden sollen.

Students_Index_page

Screenshots, die die Seite

Der Benutzeroberflächenstil dieser Website orientiert sich an den integrierten Vorlagen, sodass Sie mit dieses Tutorial hauptsächlich auf die Verwendung von Entity Framework konzentriert.

Voraussetzungen

In den Anweisungen und Screenshots in diesem Tutorial wird davon ausgegangen, dass Sie Visual Studio 2012 oder Visual Studio 2012 Express for Web verwenden, wobei das neueste Update und das azure SDK für .NET ab Juli 2013 installiert sind. Sie können all dies über den folgenden Link abrufen:

Azure SDK für .NET (Visual Studio 2012)

Wenn Sie Visual Studio installiert haben, werden über den obigen Link alle fehlenden Komponenten installiert. Wenn Sie nicht über Visual Studio verfügen, wird über den Link Visual Studio 2012 Express für Web installiert. Sie können Visual Studio 2013 verwenden, aber einige der erforderlichen Verfahren und Bildschirme unterscheiden sich.

Erstellen einer MVC-Webanwendung

Öffnen Sie Visual Studio, und erstellen Sie mithilfe der Vorlage ASP.NET MVC 4-Webanwendung ein neues C#-Projekt mit dem Namen "ContosoUniversity". Stellen Sie sicher, dass Sie .NET Framework 4.5 als Ziel verwenden (Sie verwenden enum Eigenschaften, und dies erfordert .NET 4.5).

New_project_dialog_box

Wählen Sie im Dialogfeld Neues ASP.NET MVC 4-Projekt die Vorlage Internetanwendung aus.

Lassen Sie die Razor-Ansichts-Engine ausgewählt, und lassen Sie das Kontrollkästchen Komponententestprojekt erstellen deaktiviert.

Klicken Sie auf OK.

Project_template_options

Einrichten des Websiteformats

Sie können das Websitemenü, das Layout und die Startseite über einige Änderungen einrichten.

Öffnen Sie Views\Shared\_Layout.cshtml, und ersetzen Sie den Inhalt der Datei durch den folgenden Code. Die Änderungen werden hervorgehoben.

<!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>

Durch diesen Code werden folgende Änderungen vorgenommen:

  • Ersetzt die Vorlageninstanzen von "Meine ASP.NET MVC-Anwendung" und "Ihr Logo hier" durch "Contoso University".
  • Fügt mehrere Aktionslinks hinzu, die später im Tutorial verwendet werden.

Ersetzen Sie in Views\Home\Index.cshtml den Inhalt der Datei durch den folgenden Code, um die Vorlagenabsätze zu ASP.NET und MVC zu entfernen:

@{
    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>
}

Ändern Sie in Controllers\HomeController.cs den Wert für ViewBag.Message in der Index Action-Methode in "Willkommen bei Contoso University!", wie im folgenden Beispiel gezeigt:

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

    return View();
}

Drücken Sie STRG+F5, um die Website auszuführen. Die Startseite mit dem Menü Standard wird angezeigt.

Contoso_University_home_page

Erstellen des Datenmodells

Als nächstes erstellen Sie Entitätsklassen für die Contoso University-Anwendung. Sie beginnen mit den folgenden drei Entitäten:

Class_diagram

Es besteht eine 1:n-Beziehung zwischen den Entitäten Student und Enrollment. Außerdem besteht eine 1:n-Beziehung zwischen den Entitäten Course und Enrollment. Das bedeutet, dass ein Student für beliebig viele Kurse angemeldet sein kann und sich für jeden Kurs eine beliebige Anzahl von Studenten anmelden kann.

In den folgenden Abschnitten erstellen Sie für jede dieser Entitäten eine Klasse.

Hinweis

Wenn Sie versuchen, das Projekt zu kompilieren, bevor Sie mit der Erstellung all dieser Entitätsklassen fertig sind, erhalten Sie Compilerfehler.

Die Entität "Student"

Student_entity

Erstellen Sie im Ordner ModelsStudent.cs , und ersetzen Sie den vorhandenen Code durch den folgenden Code:

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; }
    }
}

Die StudentID-Eigenschaft fungiert als Primärschlüsselspalte der Datenbanktabelle, die dieser Klasse entspricht. Standardmäßig interpretiert Entity Framework eine Eigenschaft namens ID oder klassennameID als Primärschlüssel.

Die Enrollments-Eigenschaft ist eine Navigationseigenschaft. Navigationseigenschaften enthalten andere Entitäten, die dieser Entität zugehörig sind. In diesem Fall enthält die Enrollments -Eigenschaft einer Student Entität alle Entitäten, die Enrollment mit dieser Student Entität verknüpft sind. Anders ausgedrückt: Wenn eine angegebene Student Zeile in der Datenbank zwei verknüpfte Enrollment Zeilen enthält (Zeilen, die den Primärschlüsselwert dieses Kursteilnehmers in der StudentID Fremdschlüsselspalte enthalten), enthält die Navigationseigenschaft Enrollments dieser Student Entität diese beiden Enrollment Entitäten.

Navigationseigenschaften werden in der Regel als virtual definiert, damit sie bestimmte Entity Framework-Funktionen wie verzögertes Laden nutzen können. (Verzögertes Laden wird später im Tutorial Lesen verwandter Daten weiter unten in dieser Reihe erläutert.

Wenn eine Navigationseigenschaft mehrere Entitäten enthalten kann (wie bei m:n- oder 1:n-Beziehungen), muss dessen Typ aus einer Liste bestehen, in der Einträge hinzugefügt, gelöscht und aktualisiert werden können – z.B.: ICollection.

Die Registrierungsentität

Enrollment_entity

Erstellen Sie im Ordner Models (Modelle) die Datei Enrollment.cs, und ersetzen Sie den vorhandenen Code durch folgenden Code:

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; }
    }
}

Die Grade-Eigenschaft ist eine Enumeration. Das Fragezeichen nach der Grade-Typdeklaration gibt an, dass die Grade-Eigenschaft NULL-Werte zulässt. Eine Note, die NULL ist, unterscheidet sich von einer Null-Note– null bedeutet, dass eine Note nicht bekannt ist oder noch nicht zugewiesen wurde.

Bei der StudentID-Eigenschaft handelt es sich um einen Fremdschlüssel, und Student ist die entsprechende Navigationseigenschaft. Eine Enrollment-Entität wird einer Student-Entität zugeordnet, damit die Eigenschaft nur eine Student-Entität enthalten kann. Dies steht im Gegensatz zu der bereits erläuterten Student.Enrollments-Navigationseigenschaft, die mehrere Enrollment-Entitäten enthalten kann.

Bei der CourseID-Eigenschaft handelt es sich um einen Fremdschlüssel, und die zugehörige Navigationseigenschaft lautet Course. Die Enrollment-Entität wird einer Course-Entität zugeordnet.

Die Entität „Course“

Course_entity

Erstellen Sie im Ordner ModelsCourse.cs, und ersetzen Sie den vorhandenen Code durch den folgenden Code:

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; }
    }
}

Die Enrollments-Eigenschaft ist eine Navigationseigenschaft. Course-Entitäten können sich auf jede beliebige Anzahl von Enrollment-Entitäten beziehen.

Weitere Informationen zu [DatabaseGenerated(DatabaseGeneratedOption. None)] -Attribut im nächsten Tutorial. Im Grunde können Sie über dieses Attribut den Primärschlüssel für den Kurs angeben, anstatt ihn von der Datenbank generieren zu lassen.

Erstellen des Datenbankkontexts

Die Standard-Klasse, die die Entity Framework-Funktionalität für ein bestimmtes Datenmodell koordiniert, ist die Datenbankkontextklasse. Sie erstellen diese Klasse, indem Sie von der System.Data.Entity.DbContext-Klasse ableiten. Sie geben in Ihrem Code an, welche Entitäten im Datenmodell enthalten sind. Außerdem können Sie bestimmte Entity Framework-Verhalten anpassen. In diesem Projekt heißt die Klasse SchoolContext.

Erstellen Sie einen Ordner mit dem Namen DAL (für Datenzugriffsebene). Erstellen Sie in diesem Ordner eine neue Klassendatei mit dem Namen SchoolContext.cs, und ersetzen Sie den vorhandenen Code durch den folgenden Code:

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>();
        }
    }
}

Dieser Code erstellt eine DbSet-Eigenschaft für jede Entitätsgruppe. In der Entity Framework-Terminologie entspricht ein Entitätssatz in der Regel einer Datenbanktabelle, und eine Entität entspricht einer Zeile in der Tabelle.

Die modelBuilder.Conventions.Remove -Anweisung in der OnModelCreating-Methode verhindert, dass Tabellennamen pluralisiert werden. Wenn Sie dies nicht getan haben, werden die generierten Tabellen mit den Namen , Coursesund EnrollmentsbenanntStudents. Stattdessen sind Studentdie Tabellennamen , Courseund Enrollment. Entwickler sind sich uneinig darüber, ob Tabellennamen im Plural stehen sollten oder nicht. In diesem Tutorial wird das singulare Formular verwendet, aber der wichtige Punkt ist, dass Sie das gewünschte Formular auswählen können, indem Sie diese Codezeile einschließen oder weglassen.

SQL Server Express LocalDB

LocalDB ist eine einfache Version der SQL Server Express-Datenbank-Engine, die bei Bedarf gestartet und im Benutzermodus ausgeführt wird. LocalDB wird in einem speziellen Ausführungsmodus von SQL Server Express ausgeführt, mit dem Sie mit Datenbanken als .mdf Dateien arbeiten können. In der Regel werden LocalDB-Datenbankdateien im App_Data Ordner eines Webprojekts gespeichert. Das Benutzer-instance-Feature in SQL Server Express ermöglicht es Ihnen auch, mit .mdf Dateien zu arbeiten, aber das Feature "Benutzer instance" ist veraltet. Daher wird LocalDB für die Arbeit mit .mdf-Dateien empfohlen.

In der Regel wird SQL Server Express nicht für Produktionswebanwendungen verwendet. LocalDB wird insbesondere nicht für die Produktionsverwendung mit einer Webanwendung empfohlen, da sie nicht für die Verwendung mit IIS konzipiert ist.

In Visual Studio 2012 und höheren Versionen wird LocalDB standardmäßig mit Visual Studio installiert. In Visual Studio 2010 und früheren Versionen wird SQL Server Express (ohne LocalDB) standardmäßig mit Visual Studio installiert. Sie müssen es manuell installieren, wenn Sie Visual Studio 2010 verwenden.

In diesem Tutorial arbeiten Sie mit LocalDB, sodass die Datenbank im Ordner App_Data als .mdf Datei gespeichert werden kann. Öffnen Sie die Stammdatei Web.config, und fügen Sie der connectionStrings Auflistung eine neue Verbindungszeichenfolge hinzu, wie im folgenden Beispiel gezeigt. (Stellen Sie sicher, dass Sie die Web.config-Datei im Stammprojektordner aktualisieren. Es gibt auch eine Web.config Datei im Unterordner Ansichten , die Sie nicht aktualisieren müssen.)

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

Standardmäßig sucht das Entity Framework nach einem Verbindungszeichenfolge mit dem gleichen Namen wie die DbContext Klasse (SchoolContext für dieses Projekt). Die Verbindungszeichenfolge, die Sie hinzugefügt haben, gibt eine LocalDB-Datenbank namens ContosoUniversity.mdf im Ordner App_Data an. Weitere Informationen finden Sie unter SQL Server Verbindungszeichenfolgen für ASP.NET Webanwendungen.

Sie müssen die Verbindungszeichenfolge nicht angeben. Wenn Sie keinen Verbindungszeichenfolge bereitstellen, erstellt Entity Framework eine für Sie. Die Datenbank befindet sich jedoch möglicherweise nicht im ordner App_data Ihrer App. Informationen dazu, wo die Datenbank erstellt wird, finden Sie unter Code First to a New Database.

Die connectionStrings Auflistung verfügt auch über eine Verbindungszeichenfolge namensDefaultConnection, die für die Mitgliedschaftsdatenbank verwendet wird. Sie werden die Mitgliedschaftsdatenbank in diesem Tutorial nicht verwenden. Der einzige Unterschied zwischen den beiden Verbindungszeichenfolgen ist der Datenbankname und der Name-Attributwert.

Einrichten und Ausführen einer Code First-Migration

Wenn Sie zum ersten Mal mit der Entwicklung einer Anwendung beginnen, ändert sich Ihr Datenmodell häufig, und jedes Mal, wenn das Modell geändert wird, wird es nicht mehr mit der Datenbank synchronisiert. Sie können das Entity Framework so konfigurieren, dass die Datenbank bei jeder Änderung des Datenmodells automatisch gelöscht und neu erstellt wird. Dies ist kein Problem in der frühen Entwicklung, da Testdaten einfach neu erstellt werden können, aber nach der Bereitstellung in der Produktion möchten Sie in der Regel das Datenbankschema aktualisieren, ohne die Datenbank zu löschen. Mit dem Migrationsfeature kann Code First die Datenbank aktualisieren, ohne sie zu löschen und neu zu erstellen. Zu beginn des Entwicklungszyklus eines neuen Projekts sollten Sie DropCreateDatabaseIfModelChanges verwenden, um die Datenbank bei jeder Modelländerung zu löschen, neu zu erstellen und neu zu seeden. Eine, die Sie für die Bereitstellung Ihrer Anwendung vorbereiten, können Sie in den Migrationsansatz konvertieren. In diesem Tutorial verwenden Sie nur Migrationen. Weitere Informationen finden Sie unter Code First-Migrationen- und Migrations-Screencastserie.

Aktivieren von Code First-Migrationen

  1. Klicken Sie im Menü Extras auf NuGet-Paket-Manager und dann auf Paket-Manager-Konsole.

    Selecting_Package_Manager_Console

  2. Geben Sie an der PM> Eingabeaufforderung den folgenden Befehl ein:

    enable-migrations -contexttypename SchoolContext
    

    Befehl

    Dieser Befehl erstellt einen Migrationsordner im Projekt ContosoUniversity und fügt in diesem Ordner eine Configuration.cs Datei ab, die Sie zum Konfigurieren von Migrationen bearbeiten können.

    Migrationsordner

    Die Configuration -Klasse enthält eine Seed Methode, die aufgerufen wird, wenn die Datenbank erstellt und jedes Mal aktualisiert wird, wenn sie nach einer Datenmodelländerung aktualisiert wird.

    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" }
            //    );
            //
        }
    }
    

    Mit dieser Seed Methode können Sie Testdaten in die Datenbank einfügen, nachdem Code First sie erstellt oder aktualisiert hat.

Einrichten der Seed-Methode

Die Seed-Methode wird ausgeführt, wenn Code First-Migrationen die Datenbank erstellt und die Datenbank jedes Mal auf die neueste Migration aktualisiert. Der Zweck der Seed-Methode besteht darin, Es Ihnen zu ermöglichen, Daten in Ihre Tabellen einzufügen, bevor die Anwendung zum ersten Mal auf die Datenbank zugreift.

In früheren Versionen von Code First war es vor der Veröffentlichung von Migrationen üblich Seed , dass Methoden Testdaten einfügen, da bei jeder Modelländerung während der Entwicklung die Datenbank vollständig gelöscht und von Grund auf neu erstellt werden musste. Bei Code First-Migrationen werden Testdaten nach Datenbankänderungen beibehalten, sodass das Einschließen von Testdaten in der Seed-Methode in der Regel nicht erforderlich ist. Tatsächlich möchten Sie nicht, dass die Seed -Methode Testdaten einfügt, wenn Sie Migrationen verwenden, um die Datenbank in der Produktion bereitzustellen, da die Methode in der Seed Produktion ausgeführt wird. In diesem Fall soll die Seed Methode nur die Daten in die Datenbank einfügen, die in die Produktion eingefügt werden sollen. Sie können z. B. in der Datenbank tatsächliche Abteilungsnamen in die Tabelle aufnehmen, wenn die Anwendung in der Department Produktion verfügbar wird.

In diesem Tutorial verwenden Sie Migrationen für die Bereitstellung, aber Ihre Seed Methode fügt trotzdem Testdaten ein, um die Funktionsweise der Anwendungsfunktionalität zu erleichtern, ohne viele Daten manuell einfügen zu müssen.

  1. Ersetzen Sie den Inhalt der Configuration.cs-Datei durch den folgenden Code, wodurch Testdaten in die neue Datenbank geladen werden.

    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();
          }
       }
    }
    

    Die Seed-Methode verwendet das Datenbankkontextobjekt als Eingabeparameter, und der Code in der -Methode verwendet dieses Objekt, um der Datenbank neue Entitäten hinzuzufügen. Für jeden Entitätstyp erstellt der Code eine Auflistung neuer Entitäten, fügt sie der entsprechenden DbSet-Eigenschaft hinzu und speichert dann die Änderungen in der Datenbank. Es ist nicht erforderlich, die SaveChanges-Methode nach jeder Gruppe von Entitäten aufzurufen, wie hier ausgeführt, aber dadurch können Sie die Quelle eines Problems finden, wenn eine Ausnahme auftritt, während der Code in die Datenbank schreibt.

    Einige der Anweisungen, die Daten einfügen, verwenden die AddOrUpdate-Methode , um einen Upsert-Vorgang auszuführen. Da die Seed Methode mit jeder Migration ausgeführt wird, können Sie nicht einfach Daten einfügen, da die Zeilen, die Sie hinzufügen möchten, bereits nach der ersten Migration vorhanden sind, die die Datenbank erstellt. Der Vorgang "upsert" verhindert Fehler, die auftreten würden, wenn Sie versuchen, eine bereits vorhandene Zeile einzufügen, aber er setzt alle Änderungen an Daten außer Kraft , die Sie möglicherweise beim Testen der Anwendung vorgenommen haben. Bei Testdaten in einigen Tabellen möchten Sie möglicherweise nicht, dass dies geschieht: In einigen Fällen, wenn Sie Daten während des Tests ändern, möchten Sie, dass ihre Änderungen nach Datenbankupdates beibehalten werden. In diesem Fall möchten Sie einen bedingten Einfügevorgang ausführen: Fügen Sie eine Zeile nur ein, wenn sie noch nicht vorhanden ist. Die Seed-Methode verwendet beide Ansätze.

    Der erste Parameter, der an die AddOrUpdate-Methode übergeben wird, gibt die Eigenschaft an, mit der überprüft werden soll, ob eine Zeile bereits vorhanden ist. Für die von Ihnen bereitgestellten Testschülerdaten kann die LastName -Eigenschaft zu diesem Zweck verwendet werden, da jeder Nachname in der Liste eindeutig ist:

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

    Bei diesem Code wird davon ausgegangen, dass Nachnamen eindeutig sind. Wenn Sie einen Kursteilnehmer mit doppeltem Nachnamen manuell hinzufügen, erhalten Sie bei der nächsten Migration die folgende Ausnahme.

    Sequenz enthält mehr als ein Element

    Weitere Informationen zur AddOrUpdate Methode finden Sie im Blog von Julie Lerman unter Take care with EF 4.3 AddOrUpdate Method .

    Der Code, der Entitäten hinzufügt Enrollment , verwendet die AddOrUpdate -Methode nicht. Es überprüft, ob eine Entität bereits vorhanden ist, und fügt die Entität ein, wenn sie nicht vorhanden ist. Dieser Ansatz behält Änderungen bei, die Sie an einer Registrierungsstufe vornehmen, wenn Migrationen ausgeführt werden. Der Code durchläuft jedes Element der EnrollmentListe . Wenn die Registrierung nicht in der Datenbank gefunden wird, wird die Registrierung der Datenbank hinzugefügt. Wenn Sie die Datenbank zum ersten Mal aktualisieren, ist die Datenbank leer, sodass jede Registrierung hinzugefügt wird.

    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);
        }
    }
    

    Informationen zum Debuggen der Seed Methode und zum Umgang mit redundanten Daten wie zwei Kursteilnehmern mit dem Namen "Alexander Carson" finden Sie unter Seeding and Debugging Entity Framework (EF) DBs im Blog von Rick Anderson.

  2. Erstellen Sie das Projekt.

Erstellen und Ausführen der ersten Migration

  1. Geben Sie im Fenster Paket-Manager-Konsole die folgenden Befehle ein:

    add-migration InitialCreate
    update-database
    

    Screenshot: Fenster

    Der add-migration Befehl fügt dem Ordner Migration eine [DateStamp]_InitialCreate.cs-Datei hinzu, die Code enthält, der die Datenbank erstellt. Der erste Parameter (InitialCreate) wird für den Dateinamen verwendet und kann beliebig sein. Sie wählen in der Regel ein Wort oder einen Ausdruck aus, der die Vorgänge in der Migration zusammenfasst. Sie können einer späteren Migration beispielsweise den Namen „AddDepartmentTable“ geben.

    Migrationsordner mit der ersten Migration

    Die Up -Methode der InitialCreate -Klasse erstellt die Datenbanktabellen, die den Datenmodellentitätssätzen entsprechen, und die Down Methode löscht sie. Die Migrationsfunktion ruft die Methode Up auf, um die Datenmodelländerungen für eine Migration zu implementieren. Wenn Sie einen Befehl eingeben, um ein Rollback für das Update auszuführen, ruft die Migrationsfunktion die Methode Down auf. Der folgende Code zeigt den Inhalt der InitialCreate Datei an:

    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");
            }
        }
    }
    

    Der update-database Befehl führt die Up -Methode aus, um die Datenbank zu erstellen, und führt dann die Seed -Methode aus, um die Datenbank aufzufüllen.

Für Ihr Datenmodell wurde nun eine SQL Server Datenbank erstellt. Der Name der Datenbank lautet ContosoUniversity, und die .mdf Datei befindet sich im App_Data Ordner Ihres Projekts, da Sie dies in Ihrem Verbindungszeichenfolge angegeben haben.

Sie können entweder Server Explorer oder SQL Server Objekt-Explorer (SSOX) verwenden, um die Datenbank in Visual Studio anzuzeigen. In diesem Tutorial verwenden Sie Server Explorer. In Visual Studio Express 2012 für Web heißt Server ExplorerDatenbank Explorer.

  1. Klicken Sie im Menü Ansicht auf Server Explorer.

  2. Klicken Sie auf das Symbol Verbindung hinzufügen .

    Screenshot des Fensters

  3. Wenn Sie zum Dialogfeld Datenquelle auswählen aufgefordert werden, klicken Sie auf Microsoft SQL Server, und klicken Sie dann auf Weiter.

    Screenshot des Dialogfelds Datenquelle auswählen Die Microsoft S Q L Server-Datenquelle ist ausgewählt.

  4. Geben Sie im Dialogfeld Verbindung hinzufügen(localdb)\v11.0 als Servername ein. Wählen Sie unter Datenbankname auswählen oder eingeben die Option ContosoUniversity aus.

    Screenshot des Dialogfelds Verbindung hinzufügen Der Beispielservername und die Contoso University-Datenbank sind hervorgehoben.

  5. Klicken Sie auf OK.

  6. Erweitern Sie SchoolContext und dann Tabellen.

    Screenshot: Seite

  7. Klicken Sie mit der rechten Maustaste auf die Tabelle Student , und klicken Sie auf Tabellendaten anzeigen , um die erstellten Spalten und die Zeilen anzuzeigen, die in die Tabelle eingefügt wurden.

    Kursteilnehmertabelle

Erstellen eines Schülercontrollers und -ansichten

Der nächste Schritt besteht darin, einen ASP.NET MVC-Controller und Ansichten in Ihrer Anwendung zu erstellen, die mit einer dieser Tabellen funktionieren können.

  1. Um einen Student Controller zu erstellen, klicken Sie mit der rechten Maustaste auf den Ordner Controller in Projektmappen-Explorer, wählen Sie Hinzufügen aus, und klicken Sie dann auf Controller. Wählen Sie im Dialogfeld Controller hinzufügen die folgenden Optionen aus, und klicken Sie dann auf Hinzufügen:

    • Controllername: StudentController.

    • Vorlage: MVC-Controller mit Lese-/Schreibaktionen und Ansichten unter Verwendung von Entity Framework.

    • Modellklasse: Student (ContosoUniversity.Models). (Wenn diese Option in der Dropdownliste nicht angezeigt wird, erstellen Sie das Projekt, und versuchen Sie es erneut.)

    • Datenkontextklasse: SchoolContext (ContosoUniversity.Models).

    • Ansichten: Razor (CSHTML). (Der Standardwert.)

      Add_Controller_dialog_box_for_Student_controller

  2. Visual Studio öffnet die Datei Controller\StudentController.cs . Sie sehen, dass eine Klassenvariable erstellt wurde, die ein Datenbankkontextobjekt instanziiert:

    private SchoolContext db = new SchoolContext();
    

    Die Index Aktionsmethode ruft eine Liste von Kursteilnehmern aus der Entität Students ab, die festgelegt ist, indem die Students Eigenschaft des Datenbankkontexts instance gelesen wird:

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

    Die Ansicht Student\Index.cshtml zeigt diese Liste in einer Tabelle an:

    <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. Drücken Sie STRG+F5, um das Projekt auszuführen.

    Klicken Sie auf die Registerkarte Schüler , um die von der Methode eingefügten Seed Testdaten anzuzeigen.

    Seite

Konventionen

Die Menge an Code, die Sie schreiben mussten, damit Entity Framework eine vollständige Datenbank für Sie erstellen kann, ist aufgrund der Verwendung von Konventionen oder Annahmen, die das Entity Framework vornimmt, minimal. Einige davon wurden bereits festgestellt:

  • Die pluralisierten Formen von Entitätsklassennamen werden als Tabellennamen verwendet.
  • Eigenschaftennamen von Entitäten werden als Spaltennamen verwendet.
  • Entitätseigenschaften mit dem Namen ID oder KlassennameID werden als Primärschlüsseleigenschaften erkannt.

Sie haben gesehen, dass Konventionen überschrieben werden können (z. B. haben Sie angegeben, dass Tabellennamen nicht pluralisiert werden sollen), und Sie erfahren mehr über Konventionen und deren Überschreibung im Tutorial Erstellen eines komplexeren Datenmodells weiter unten in dieser Reihe. Weitere Informationen finden Sie unter Code First-Konventionen.

Zusammenfassung

Sie haben jetzt eine einfache Anwendung erstellt, die das Entity Framework und SQL Server Express zum Speichern und Anzeigen von Daten verwendet. Im folgenden Tutorial erfahren Sie, wie Sie grundlegende CRUD-Vorgänge (Erstellen, Lesen, Aktualisieren, Löschen) ausführen. Sie können am Ende dieser Seite Feedback hinterlassen. Bitte teilen Sie uns mit, wie Ihnen dieser Teil des Tutorials gefallen hat und wie wir ihn verbessern konnten.

Links zu anderen Entity Framework-Ressourcen finden Sie in der Inhaltsübersicht ASP.NET Datenzugriff.