Udostępnij za pośrednictwem


Tworzenie modelu danych platformy Entity Framework dla aplikacji MVC ASP.NET (1 z 10)

Autor: Tom Dykstra

Uwaga

Dostępna jest nowsza wersja tej serii samouczków dla programów Visual Studio 2013, Entity Framework 6 i MVC 5.

Przykładowa aplikacja internetowa Contoso University pokazuje, jak tworzyć aplikacje ASP.NET MVC 4 przy użyciu platform Entity Framework 5 i Visual Studio 2012. Przykładowa aplikacja to witryna internetowa fikcyjnego uniwersytetu Contoso. Obejmuje ona funkcje, takie jak wstęp dla uczniów, tworzenie kursów i zadania instruktora. W tej serii samouczków wyjaśniono, jak utworzyć przykładową aplikację Contoso University.

Kod pierwszy

Istnieją trzy sposoby pracy z danymi w programie Entity Framework: Database First, Model First i Code First. Ten samouczek jest przeznaczony dla aplikacji Code First. Aby uzyskać informacje o różnicach między tymi przepływami pracy i wskazówkami dotyczącymi sposobu wybierania najlepszego dla danego scenariusza, zobacz Entity Framework Development Workflows (Przepływy pracy programowania w programie Entity Framework).

MVC

Przykładowa aplikacja jest oparta na ASP.NET MVC. Jeśli wolisz pracować z modelem ASP.NET Web Forms, zapoznaj się z serią samouczków Powiązanie modelu i formularze sieci Web oraz ASP.NET mapą zawartości dostępu do danych.

Wersje oprogramowania

Pokazano w samouczku Działa również z
Windows 8 Windows 7
Visual Studio 2012 Visual Studio 2012 Express for Web. Jest to automatycznie instalowane przez zestaw Windows Azure SDK, jeśli nie masz jeszcze programu VS 2012 lub VS 2012 Express for Web. Program Visual Studio 2013 powinien działać, ale samouczek nie został z nim przetestowany, a niektóre opcje menu i okna dialogowe są inne. Do wdrożenia platformy Windows Azure wymagany jest program VS 2013 zestawu SDK platformy Windows Azure.
.NET 4.5 Większość wyświetlanych funkcji będzie działać na platformie .NET 4, ale niektóre z nich nie będą działać. Na przykład obsługa wyliczenia w programie EF wymaga platformy .NET 4.5.
Entity Framework 5
Windows Azure SDK 2.1 Jeśli pominiesz kroki wdrażania platformy Windows Azure, nie potrzebujesz zestawu SDK. Po wydaniu nowej wersji zestawu SDK link zainstaluje nowszą wersję. W takim przypadku może być konieczne dostosowanie niektórych instrukcji do nowego interfejsu użytkownika i funkcji.

Pytania

Jeśli masz pytania, które nie są bezpośrednio związane z samouczkiem, możesz opublikować je na forum ASP.NET Entity Framework, forum Entity Framework i LINQ to Entities lub StackOverflow.com.

Podziękowania

Zapoznaj się z ostatnim samouczkiem z serii, aby uzyskać potwierdzenie i notatkę dotyczącą języka VB.

Aplikacja internetowa Uniwersytetu Contoso

Aplikacja, którą utworzysz w tych samouczkach, jest prostą witryną internetową uniwersytetu.

Użytkownicy mogą wyświetlać i aktualizować informacje o uczniach, kursach i instruktorach. Oto kilka ekranów, które utworzysz.

Students_Index_page

Zrzuty ekranu pokazujące przykładową stronę wyszukiwania studentów aplikacji internetowej Contoso University i stronę Tworzenie nowego studenta.

Styl interfejsu użytkownika tej witryny był zbliżony do tego, co jest generowane przez wbudowane szablony, dzięki czemu samouczek może skupić się głównie na sposobie korzystania z programu Entity Framework.

Wymagania wstępne

Wskazówki i zrzuty ekranu w tym samouczku zakładają, że używasz programu Visual Studio 2012 lub Visual Studio 2012 Express for Web z najnowszą aktualizacją i zestawem Azure SDK dla platformy .NET zainstalowanym od lipca 2013 r. Wszystko to możesz uzyskać za pomocą następującego linku:

Zestaw Azure SDK dla platformy .NET (Visual Studio 2012)

Jeśli masz zainstalowany program Visual Studio, powyższe łącze spowoduje zainstalowanie wszystkich brakujących składników. Jeśli nie masz programu Visual Studio, link spowoduje zainstalowanie programu Visual Studio 2012 Express for Web. Możesz użyć programu Visual Studio 2013, ale niektóre z wymaganych procedur i ekranów będą się różnić.

Tworzenie aplikacji internetowej MVC

Otwórz program Visual Studio i utwórz nowy projekt języka C# o nazwie "ContosoUniversity" przy użyciu szablonu aplikacji internetowej ASP.NET MVC 4. Upewnij się, że docelowy jest program .NET Framework 4.5 (będziesz używać enum właściwości i wymaga platformy .NET 4.5).

New_project_dialog_box

W oknie dialogowym Nowy projekt MVC 4 ASP.NET wybierz szablon Aplikacja internetowa.

Pozostaw zaznaczony aparat widoku Razor i pozostaw pole wyboru Utwórz projekt testu jednostkowego.

Kliknij przycisk OK.

Project_template_options

Konfigurowanie stylu witryny

Kilka prostych zmian spowoduje skonfigurowanie menu witryny, układu i strony głównej.

Otwórz plik Views\Shared\_Layout.cshtml i zastąp zawartość pliku następującym kodem. Zmiany są wyróżnione.

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

Ten kod wprowadza następujące zmiany:

  • Zastępuje wystąpienia szablonu "My ASP.NET MVC Application" i "your logo here" na "Contoso University".
  • Dodaje kilka linków akcji, które będą używane w dalszej części samouczka.

W pliku Views\Home\Index.cshtml zastąp zawartość pliku następującym kodem, aby wyeliminować akapity szablonu dotyczące ASP.NET i 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>
}

W controllers\HomeController.cs zmień wartość dla ViewBag.Message w metodzie Index Action na "Welcome to Contoso University!", jak pokazano w poniższym przykładzie:

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

    return View();
}

Naciśnij CTRL+F5, aby uruchomić witrynę. Zostanie wyświetlona strona główna z menu głównym.

Contoso_University_home_page

Tworzenie modelu danych

Następnie utworzysz klasy jednostek dla aplikacji Contoso University. Zaczniesz od następujących trzech jednostek:

Class_diagram

Istnieje relacja jeden do wielu między jednostkami Student i Enrollment , a istnieje relacja jeden do wielu między jednostkami Course i Enrollment . Innymi słowy, student może być zarejestrowany w dowolnej liczbie kursów, a kurs może mieć dowolną liczbę uczniów zarejestrowanych w nim.

W poniższych sekcjach utworzysz klasę dla każdej z tych jednostek.

Uwaga

Jeśli spróbujesz skompilować projekt przed zakończeniem tworzenia wszystkich tych klas jednostek, zostaną wyświetlone błędy kompilatora.

Jednostka ucznia

Student_entity

W folderze Models utwórz Student.cs i zastąp istniejący kod następującym kodem:

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

Właściwość StudentID stanie się kolumną klucza podstawowego tabeli bazy danych, która odpowiada tej klasie. Domyślnie platforma Entity Framework interpretuje właściwość o nazwie ID lub klasie ID jako klucz podstawowy.

Właściwość Enrollments jest właściwością nawigacji. Właściwości nawigacji przechowują inne jednostki powiązane z tą jednostką. W takim przypadku Enrollments właściwość Student jednostki będzie przechowywać wszystkie Enrollment jednostki powiązane z tą Student jednostką. Innymi słowy, jeśli dany Student wiersz w bazie danych zawiera dwa powiązane Enrollment wiersze (wiersze zawierające podstawową wartość klucza ucznia w kolumnie StudentID klucza obcego), Student właściwość nawigacji tej jednostki Enrollments będzie zawierać te dwie Enrollment jednostki.

Właściwości nawigacji są zwykle definiowane jako virtual tak, aby mogły korzystać z niektórych funkcji programu Entity Framework, takich jak ładowanie leniwe. (Ładowanie z opóźnieniem zostanie wyjaśnione później, w Samouczek dotyczący powiązanych danych w dalszej części tej serii.

Jeśli właściwość nawigacji może zawierać wiele jednostek (jak w relacjach wiele do wielu lub jeden do wielu), jej typ musi być listą, w której można dodawać, usuwać i aktualizować wpisy, takie jak ICollection.

Jednostka rejestracji

Enrollment_entity

W folderze Models utwórz Enrollment.cs i zastąp istniejący kod następującym kodem:

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

Właściwość Grade jest wyliczeniową. Znak zapytania po Grade deklaracji typu wskazuje, że Grade właściwość jest dopuszczana do wartości null. Klasa o wartości null różni się od klasy zerowej — wartość null oznacza, że ocena nie jest znana lub nie została jeszcze przypisana.

Właściwość StudentID jest kluczem obcym, a odpowiadająca mu właściwość nawigacji to Student. Jednostka Enrollment jest skojarzona z jedną Student jednostką, więc właściwość może przechowywać tylko jedną Student jednostkę (w przeciwieństwie do Student.Enrollments właściwości nawigacji, która może zawierać wiele Enrollment jednostek).

Właściwość CourseID jest kluczem obcym, a odpowiadająca mu właściwość nawigacji to Course. Jednostka Enrollment jest skojarzona z jedną jednostką Course .

Jednostka kursu

Course_entity

W folderze Models utwórz Course.cs, zastępując istniejący kod następującym kodem:

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

Właściwość Enrollments jest właściwością nawigacji. Jednostka Course może być powiązana z dowolną Enrollment liczbą jednostek.

Więcej informacji o [DatabaseGenerated(DatabaseGenerated(DatabaseGeneratedOption). Brak)] atrybut w następnym samouczku. Zasadniczo ten atrybut umożliwia wprowadzenie klucza podstawowego dla kursu zamiast generowania bazy danych.

Tworzenie kontekstu bazy danych

Główną klasą, która koordynuje funkcje programu Entity Framework dla danego modelu danych, jest klasa kontekstu bazy danych. Ta klasa jest tworzona przez wyprowadzenie z klasy System.Data.Entity.DbContext . W kodzie określisz, które jednostki są uwzględnione w modelu danych. Można również dostosować pewne zachowanie platformy Entity Framework. W tym projekcie klasa nosi nazwę SchoolContext.

Utwórz folder o nazwie DAL (dla warstwy dostępu do danych). W tym folderze utwórz nowy plik klasy o nazwie SchoolContext.cs i zastąp istniejący kod następującym kodem:

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

Ten kod tworzy właściwość DbSet dla każdego zestawu jednostek. W terminologii platformy Entity Framework zestaw jednostek zwykle odpowiada tabeli bazy danych, a jednostka odpowiada wierszowi w tabeli.

Instrukcja modelBuilder.Conventions.Remove w metodzie OnModelCreating uniemożliwia tworzenie nazw tabel w liczbie mnogiej. Jeśli tego nie zrobisz, wygenerowane tabele będą miały nazwę Students, Coursesi Enrollments. Zamiast tego nazwy tabel to Student, Coursei Enrollment. Deweloperzy nie zgadzają się, czy nazwy tabel powinny być w liczbie mnogiej, czy nie. W tym samouczku użyto pojedynczego formularza, ale ważnym punktem jest wybranie niezależnie od preferowanego formularza przez dołączenie lub pominięcie tego wiersza kodu.

SQL Server Express LocalDB

LocalDB to uproszczona wersja aparatu bazy danych SQL Server Express, która uruchamia się na żądanie i działa w trybie użytkownika. Baza danych LocalDB działa w specjalnym trybie wykonywania programu SQL Server Express, który umożliwia pracę z bazami danych jako pliki .mdf . Zazwyczaj pliki bazy danych LocalDB są przechowywane w folderze App_Data projektu internetowego. Funkcja wystąpienia użytkownika w programie SQL Server Express umożliwia również pracę z plikami .mdf , ale funkcja wystąpienia użytkownika jest przestarzała, dlatego usługa LocalDB jest zalecana do pracy z plikami .mdf .

Zazwyczaj program SQL Server Express nie jest używany w przypadku produkcyjnych aplikacji internetowych. W szczególności baza danych LocalDB nie jest zalecana do użytku produkcyjnego z aplikacją internetową, ponieważ nie jest przeznaczona do pracy z usługami IIS.

W programie Visual Studio 2012 i nowszych wersjach baza danych LocalDB jest instalowana domyślnie w programie Visual Studio. W programie Visual Studio 2010 i starszych wersjach program SQL Server Express (bez bazy danych LocalDB) jest instalowany domyślnie w programie Visual Studio; Musisz zainstalować go ręcznie, jeśli używasz programu Visual Studio 2010.

W tym samouczku będziesz pracować z bazą danych LocalDB, aby baza danych mogła być przechowywana w folderze App_Data jako plik .mdf . Otwórz główny plik Web.config i dodaj nowy parametry połączenia do connectionStrings kolekcji, jak pokazano w poniższym przykładzie. (Upewnij się, że zaktualizowano Plik Web.config w głównym folderze projektu. W podfolderze Views nie trzeba aktualizować pliku Web.config.

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

Domyślnie program Entity Framework szuka parametry połączenia o nazwie takiej samej jak DbContext klasa (SchoolContext dla tego projektu). Dodany parametry połączenia określa bazę danych LocalDB o nazwie ContosoUniversity.mdf znajdującą się w folderze App_Data. Aby uzyskać więcej informacji, zobacz Sql Server Connection Strings for ASP.NET Web Applications (Parametry połączenia programu SQL Server dla aplikacji internetowych ASP.NET).

Nie musisz określać parametry połączenia. Jeśli nie podasz parametry połączenia, program Entity Framework utworzy go dla Ciebie, jednak baza danych może nie znajdować się w folderze App_data aplikacji. Aby uzyskać informacje na temat miejsca utworzenia bazy danych, zobacz Code First to a New Database (Kod pierwszy do nowej bazy danych).

Kolekcja connectionStrings zawiera również parametry połączenia o nazwieDefaultConnection, która jest używana dla bazy danych członkostwa. W tym samouczku nie będziesz używać bazy danych członkostwa. Jedyną różnicą między dwoma parametry połączenia jest nazwa bazy danych i wartość atrybutu nazwy.

Konfigurowanie i wykonywanie migracji Code First

Po pierwszym rozpoczęciu tworzenia aplikacji model danych zmienia się często i za każdym razem, gdy model ulegnie synchronizacji z bazą danych. Program Entity Framework można skonfigurować tak, aby automatycznie usuwał i ponownie tworzył bazę danych za każdym razem, gdy zmieniasz model danych. Nie jest to problem na wczesnym etapie programowania, ponieważ dane testowe są łatwo tworzone ponownie, ale po wdrożeniu w środowisku produkcyjnym zwykle chcesz zaktualizować schemat bazy danych bez porzucania bazy danych. Funkcja Migracje umożliwia aktualizację bazy danych za pomocą funkcji Code First bez porzucania i ponownego tworzenia. Na początku cyklu tworzenia nowego projektu można użyć funkcji DropCreateDatabaseIfModelChanges do usunięcia, ponownego utworzenia i ponownego rozmieszczania bazy danych za każdym razem, gdy zmienia się model. Możesz przystąpić do wdrażania aplikacji, którą można przekonwertować na podejście do migracji. W tym samouczku będziesz używać tylko migracji. Aby uzyskać więcej informacji, zobacz Migracje Code First i migrations Screencast Series.

Włączanie Migracje Code First

  1. W menu Narzędzia kliknij pozycję Menedżer pakietów NuGet, a następnie kliknij pozycję Konsola menedżera pakietów.

    Selecting_Package_Manager_Console

  2. PM> W wierszu polecenia wprowadź następujące polecenie:

    enable-migrations -contexttypename SchoolContext
    

    enable-migrations — polecenie

    To polecenie tworzy folder Migrations w projekcie ContosoUniversity i umieszcza w tym folderze plik Configuration.cs , który można edytować w celu skonfigurowania migracji.

    Folder Migracje

    Klasa Configuration zawiera metodę wywoływaną Seed podczas tworzenia bazy danych i za każdym razem, gdy jest aktualizowana po zmianie modelu danych.

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

    Celem tej Seed metody jest umożliwienie wstawiania danych testowych do bazy danych po utworzeniu lub zaktualizowaniu przez program Code First.

Konfigurowanie metody Seed

Metoda Seed jest uruchamiana, gdy Migracje Code First tworzy bazę danych i za każdym razem, gdy aktualizuje bazę danych do najnowszej migracji. Celem metody Seed jest umożliwienie wstawiania danych do tabel przed uzyskaniem przez aplikację dostępu do bazy danych po raz pierwszy.

We wcześniejszych wersjach programu Code First, przed wydaniem migracji, często Seed zdarzało się, że metody wstawiania danych testowych, ponieważ każda zmiana modelu podczas opracowywania bazy danych musiała zostać całkowicie usunięta i utworzona od podstaw. W przypadku Migracje Code First dane testowe są zachowywane po zmianie bazy danych, więc uwzględnienie danych testowych w metodzie Seed zwykle nie jest konieczne. W rzeczywistości nie chcesz Seed , aby metoda wstawiła dane testowe, jeśli użyjesz funkcji Migrations do wdrożenia bazy danych w środowisku produkcyjnym, ponieważ Seed metoda zostanie uruchomiona w środowisku produkcyjnym. W takim przypadku chcesz Seed , aby metoda wstawiła do bazy danych tylko te dane, które mają zostać wstawione do środowiska produkcyjnego. Na przykład możesz chcieć, aby baza danych zawierała rzeczywiste nazwy działów w Department tabeli, gdy aplikacja stanie się dostępna w środowisku produkcyjnym.

W tym samouczku będziesz używać funkcji Migracje do wdrożenia, ale Seed metoda wstawi dane testowe mimo to, aby ułatwić sprawdzenie, jak działa funkcja aplikacji bez konieczności ręcznego wstawiania dużej ilości danych.

  1. Zastąp zawartość pliku Configuration.cs następującym kodem, który załaduje dane testowe do nowej bazy danych.

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

    Metoda Seed przyjmuje obiekt kontekstu bazy danych jako parametr wejściowy, a kod w metodzie używa tego obiektu do dodawania nowych jednostek do bazy danych. Dla każdego typu jednostki kod tworzy kolekcję nowych jednostek, dodaje je do odpowiedniej właściwości DbSet , a następnie zapisuje zmiany w bazie danych. Nie jest konieczne wywołanie metody SaveChanges po każdej grupie jednostek, podobnie jak w tym przypadku, ale pomaga zlokalizować źródło problemu, jeśli wystąpi wyjątek podczas zapisywania kodu w bazie danych.

    Niektóre instrukcje wstawiania danych używają metody AddOrUpdate do wykonania operacji "upsert". Seed Ponieważ metoda jest uruchamiana przy każdej migracji, nie można po prostu wstawić danych, ponieważ wiersze, które próbujesz dodać, będą już dostępne po pierwszej migracji, która tworzy bazę danych. Operacja "upsert" uniemożliwia błędy, które mogą wystąpić, jeśli spróbujesz wstawić wiersz, który już istnieje, ale zastępuje wszelkie zmiany danych, które mogły zostać wprowadzone podczas testowania aplikacji. W przypadku danych testowych w niektórych tabelach możesz nie chcieć tego zrobić: w niektórych przypadkach zmiana danych podczas testowania zmian ma pozostać po aktualizacjach bazy danych. W takim przypadku chcesz wykonać operację wstawiania warunkowego: wstaw wiersz tylko wtedy, gdy jeszcze nie istnieje. Metoda Seed używa obu metod.

    Pierwszy parametr przekazany do metody AddOrUpdate określa właściwość do użycia, aby sprawdzić, czy wiersz już istnieje. W przypadku danych ucznia testowego, które podajesz, właściwość może być używana do tego celu, LastName ponieważ każde nazwisko na liście jest unikatowe:

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

    W tym kodzie przyjęto założenie, że nazwiska są unikatowe. Jeśli ręcznie dodasz ucznia ze zduplikowanymi nazwiskami, otrzymasz następujący wyjątek podczas następnej migracji.

    Sekwencja zawiera więcej niż jeden element

    Aby uzyskać więcej informacji na temat AddOrUpdate metody, zobacz Artykuł Take care with EF 4.3 AddOrUpdate Method on Julie Lerman's blog (Metoda AddOrUpdate platformy EF 4.3 na blogu Julie Lerman).

    Kod, który dodaje Enrollment jednostki, nie używa AddOrUpdate metody . Sprawdza, czy jednostka już istnieje i wstawia jednostkę, jeśli nie istnieje. Takie podejście spowoduje zachowanie zmian wprowadzonych w klasie rejestracji podczas uruchamiania migracji. Kod przechodzi przez każdy element członkowski Enrollmentlisty i jeśli rejestracja nie zostanie znaleziona w bazie danych, dodaje rejestrację do bazy danych. Podczas pierwszej aktualizacji bazy danych baza danych będzie pusta, więc doda każdą rejestrację.

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

    Aby uzyskać informacje o sposobie debugowania Seed metody i sposobie obsługi nadmiarowych danych, takich jak dwóch uczniów o nazwie "Alexander Carson", zobacz Seeding and Debug Entity Framework (EF) DBs on Rick Anderson's blog (Wdrażanie i debugowanie baz danych platformy Entity Framework (EF) na blogu Ricka Andersona.

  2. Skompiluj projekt.

Tworzenie i wykonywanie pierwszej migracji

  1. W oknie Menedżer pakietów Console (Konsola Menedżer pakietów) wprowadź następujące polecenia:

    add-migration InitialCreate
    update-database
    

    Zrzut ekranu przedstawiający okno konsoli Menedżer pakietów. Polecenia dodają podkreślenie podkreślenia migracji łącznika Initial Create and update łącznik database (Tworzenie początkowe i aktualizowanie bazy danych łączników) zostały wyróżnione.

    Polecenie add-migration dodaje do folderu Migrations plik [DateStamp]_InitialCreate.cs zawierający kod tworzący bazę danych. Pierwszy parametr (InitialCreate) jest używany dla nazwy pliku i może być dowolny; zazwyczaj wybierasz słowo lub frazę, która podsumowuje, co jest wykonywane w migracji. Na przykład można nazwać późniejszą migrację "AddDepartmentTable".

    Folder Migracje z migracją początkową

    Metoda Up InitialCreate klasy tworzy tabele bazy danych, które odpowiadają zestawom jednostek modelu danych, a Down metoda je usuwa. Migracje wywołuje metodę Up implementowania zmian modelu danych na potrzeby migracji. Po wprowadzeniu polecenia w celu wycofania aktualizacji funkcja Migrations wywołuje metodę Down . Poniższy kod przedstawia zawartość InitialCreate pliku:

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

    Polecenie update-database uruchamia metodę Up , aby utworzyć bazę danych, a następnie uruchamia Seed metodę wypełniania bazy danych.

Baza danych programu SQL Server została utworzona dla modelu danych. Nazwa bazy danych to ContosoUniversity, a plik .mdf znajduje się w folderze App_Data projektu, ponieważ jest to plik określony w parametry połączenia.

Aby wyświetlić bazę danych w programie Visual Studio, możesz użyć Eksploratora serwera lub programu SQL Server Eksplorator obiektów (SSOX). Na potrzeby tego samouczka użyjesz Eksploratora serwera. W programie Visual Studio Express 2012 for Web Eksplorator serwera nosi nazwę Eksplorator bazy danych.

  1. W menu Widok kliknij pozycję Eksplorator serwera.

  2. Kliknij ikonę Dodaj połączenie .

    Zrzut ekranu przedstawiający okno Eksploratora baz danych. Ikona Dodaj połączenie jest wyróżniona.

  3. Jeśli zostanie wyświetlony monit z oknem dialogowym Wybieranie źródła danych, kliknij pozycję Microsoft SQL Server, a następnie kliknij przycisk Kontynuuj.

    Zrzut ekranu przedstawiający okno dialogowe Wybieranie źródła danych. Wybrano źródło danych serwera Microsoft S Q L Server.

  4. W oknie dialogowym Dodawanie połączenia wprowadź wartość (localdb)\v11.0 jako nazwę serwera. W obszarze Wybierz lub wprowadź nazwę bazy danych wybierz pozycję ContosoUniversity.

    Zrzut ekranu przedstawiający okno dialogowe Dodawanie połączenia. Wyróżniono przykładową nazwę serwera i bazę danych Contoso University.

  5. Kliknij przycisk OK.

  6. Rozwiń węzeł SchoolContext , a następnie rozwiń węzeł Tabele.

    Zrzut ekranu przedstawiający stronę Eksploratora serwera. Karty Kontekst szkoły i Tabele są rozwinięte.

  7. Kliknij prawym przyciskiem myszy tabelę Student i kliknij pozycję Pokaż dane tabeli, aby wyświetlić utworzone kolumny i wiersze wstawione do tabeli.

    Tabela uczniów

Tworzenie kontrolera ucznia i widoków

Następnym krokiem jest utworzenie ASP.NET kontrolera MVC i widoków w aplikacji, które mogą współdziałać z jedną z tych tabel.

  1. Aby utworzyć kontroler, kliknij prawym przyciskiem Student myszy folder Controllers w Eksplorator rozwiązań, wybierz polecenie Dodaj, a następnie kliknij przycisk Kontroler. W oknie dialogowym Dodawanie kontrolera wprowadź następujące opcje, a następnie kliknij przycisk Dodaj:

    • Nazwa kontrolera: StudentController.

    • Szablon: kontroler MVC z akcjami i widokami odczytu/zapisu przy użyciu platformy Entity Framework.

    • Klasa modelu: Student (ContosoUniversity.Models). (Jeśli ta opcja nie jest widoczna na liście rozwijanej, skompiluj projekt i spróbuj ponownie).

    • Klasa kontekstu danych: SchoolContext (ContosoUniversity.Models).

    • Widoki: Razor (CSHTML). (Wartość domyślna).

      Add_Controller_dialog_box_for_Student_controller

  2. Program Visual Studio otwiera plik Controllers\StudentController.cs . Zostanie utworzona zmienna klasy, która tworzy wystąpienie obiektu kontekstu bazy danych:

    private SchoolContext db = new SchoolContext();
    

    Metoda Index akcji pobiera listę uczniów z zestawu jednostek Students , odczytując Students właściwość wystąpienia kontekstu bazy danych:

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

    Widok Student\Index.cshtml wyświetla tę listę w tabeli:

    <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. Naciśnij CTRL+F5, aby uruchomić projekt.

    Kliknij kartę Uczniowie, aby wyświetlić dane testowe wstawione przez metodęSeed.

    Strona indeksu ucznia

Konwencje

Ilość kodu, który trzeba było napisać, aby program Entity Framework mógł utworzyć pełną bazę danych, jest minimalny ze względu na użycie konwencji lub założeń, które wykonuje program Entity Framework. Niektóre z nich zostały już zauważone:

  • Nazwy klas jednostek są używane jako nazwy tabel w liczbie mnogiej.
  • Nazwy właściwości jednostki są używane dla nazw kolumn.
  • Właściwości jednostki o nazwie ID lub klasie ID są rozpoznawane jako właściwości klucza podstawowego.

Wiesz już, że konwencje można zastąpić (na przykład określono, że nazwy tabel nie powinny być w liczbie mnogiej) i dowiesz się więcej o konwencjach i sposobach ich zastępowania w samouczku Tworzenie bardziej złożonego modelu danych w dalszej części tej serii. Aby uzyskać więcej informacji, zobacz Code First Conventions (Konwencje code first).

Podsumowanie

Utworzono prostą aplikację, która używa programu Entity Framework i programu SQL Server Express do przechowywania i wyświetlania danych. Z poniższego samouczka dowiesz się, jak wykonywać podstawowe operacje CRUD (tworzenie, odczytywanie, aktualizowanie, usuwanie). Możesz zostawić opinię w dolnej części tej strony. Poinformuj nas o tym, jak podobała Ci się ta część samouczka i jak możemy ją ulepszyć.

Linki do innych zasobów programu Entity Framework można znaleźć na mapie zawartości dostępu do danych ASP.NET.