Создание модели данных Entity Framework для приложения ASP.NET MVC (1 из 10)
Примечание
Доступна более новая версия этой серии руководств для Visual Studio 2013, Entity Framework 6 и MVC 5.
Пример веб-приложения Университета Contoso демонстрирует создание ASP.NET приложений MVC 4 с помощью Entity Framework 5 и Visual Studio 2012. В этом примере приложения реализуется веб-сайт вымышленного университета Contoso. На нем предусмотрены различные функции, в том числе прием учащихся, создание курсов и назначение преподавателей. В этой серии учебников объясняется, как создать пример приложения Университета Contoso.
Code First
Существует три способа работы с данными в Entity Framework: Database First, Model First и Code First. Это руководство предназначено для Code First. Сведения о различиях между этими рабочими процессами и рекомендации по выбору оптимального для вашего сценария см. в разделе Рабочие процессы разработки Entity Framework.
MVC
Пример приложения основан на ASP.NET MVC. Если вы предпочитаете работать с моделью ASP.NET Web Forms, ознакомьтесь с серией учебников Привязка модели и веб-формы и ASP.NET схеме содержимого доступа к данным.
Версии программного обеспечения
Показано в руководстве Также работает с Windows 8 Windows 7 Visual Studio 2012 Visual Studio 2012 Express for Web. Пакет SDK для Windows Azure автоматически устанавливается, если у вас еще нет VS 2012 или VS 2012 Express для Интернета. Visual Studio 2013 должно работать, но учебник не был протестирован с его помощью, и некоторые меню и диалоговые окна отличаются. Для развертывания Windows Azure требуется версия VS 2013 пакета SDK для Windows Azure . .NET 4.5 Большинство показанных функций будут работать в .NET 4, а некоторые — нет. Например, для поддержки перечисления в EF требуется .NET 4.5. Entity Framework 5 Windows Azure SDK 2.1 Если вы пропустите шаги по развертыванию Windows Azure, вам не потребуется пакет SDK. После выпуска новой версии пакета SDK по ссылке будет установлена более новая версия. В этом случае может потребоваться адаптировать некоторые инструкции к новым пользовательским интерфейсам и функциям. Вопросы
Если у вас есть вопросы, которые не связаны непосредственно с этим руководством, вы можете опубликовать их на форуме ASP.NET Entity Framework, Entity Framework и LINQ to Entities форуме или StackOverflow.com.
Благодарности
В последнем руководстве серии приведены подтверждения и заметки о VB.
Веб-приложение университета Contoso
В рамках этих учебников вы будете создавать приложение, которое представляет собой простой веб-сайт университета.
Пользователи приложения могут просматривать и обновлять сведения об учащихся, курсах и преподавателях. Будет создано несколько экранов.
Стиль пользовательского интерфейса этого сайта практически полностью основан на встроенных шаблонах, поскольку это позволяет сосредоточиться на изучении и использовании возможностей платформы Entity Framework.
Предварительные требования
В руководствах и снимках экрана в этом руководстве предполагается, что вы используете Visual Studio 2012 или Visual Studio 2012 Express для Интернета с последним обновлением и пакетом AZURE SDK для .NET, установленными по состоянию на июль 2013 г. Все это можно получить по следующей ссылке:
Пакет Azure SDK для .NET (Visual Studio 2012)
Если у вас установлена Среда Visual Studio, по приведенной выше ссылке будут установлены все недостающие компоненты. Если у вас нет Visual Studio, по ссылке будет установлена Visual Studio 2012 Express для Интернета. Можно использовать Visual Studio 2013, но некоторые необходимые процедуры и экраны будут отличаться.
Создание веб-приложения MVC
Откройте Visual Studio и создайте проект C# с именем ContosoUniversity с помощью шаблона веб-приложения ASP.NET MVC 4 . Убедитесь, что вы используете платформа .NET Framework 4.5 (вы будете использовать enum
свойства, а для этого требуется .NET 4.5).
В диалоговом окне Создать проект ASP.NET MVC 4 выберите шаблон Интернет-приложение .
Оставьте выбранным подсистему представлений Razor и оставьте поле Создание проекта модульного теста проверка снято.
Нажмите кнопку ОК.
Настройка стиля сайта
Выполните незначительную настройку меню, макета и домашней страницы сайта.
Откройте Views\Shared\_Layout.cshtml и замените содержимое файла приведенным ниже кодом. Изменения выделены.
<!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>© @DateTime.Now.Year - Contoso University</p>
</div>
</div>
</footer>
@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false)
</body>
</html>
Этот код вносит следующие изменения:
- Заменяет экземпляры шаблонов "My ASP.NET MVC Application" и "your logo here" на "Contoso University".
- Добавляет несколько ссылок на действия, которые будут использоваться далее в этом руководстве.
В файле Views\Home\Index.cshtml замените содержимое файла следующим кодом, чтобы исключить абзацы шаблона о ASP.NET и 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>
}
В разделе Контроллеры\HomeController.cs измените значение ViewBag.Message
в методе Index
Action на "Добро пожаловать в университет Contoso!", как показано в следующем примере:
public ActionResult Index()
{
ViewBag.Message = "Welcome to Contoso University";
return View();
}
Нажмите клавиши CTRL+F5, чтобы запустить сайт. Вы увидите домашнюю страницу с меню main.
Создание модели данных
Теперь необходимо создать классы сущностей для приложения университета Contoso. Вы начнете со следующих трех сущностей:
Между сущностями Student
и Enrollment
, а также между сущностями Course
и Enrollment
существует отношение "один ко многим". Другими словами, учащийся может быть зарегистрирован в любом количестве курсов, а в отдельном курсе может быть зарегистрировано любое количество учащихся.
В следующих разделах создаются классы для каждой из этих сущностей.
Примечание
Если вы попытаетесь скомпилировать проект до завершения создания всех этих классов сущностей, вы получите ошибки компилятора.
Сущность Student
В папке Models создайте Student.cs и замените существующий код следующим кодом:
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; }
}
}
Свойство StudentID
будет использоваться в качестве столбца первичного ключа в таблице базы данных, соответствующей этому классу. По умолчанию Entity Framework интерпретирует свойство с именем ID
или classnameID
в качестве первичного ключа.
Свойство Enrollments
является свойством навигации. Свойства навигации содержат другие сущности, связанные с этой сущностью. В этом случае Enrollments
свойство сущности Student
будет содержать все сущности Enrollment
, связанные с этой Student
сущностью. Другими словами, если заданная Student
строка в базе данных содержит две связанные Enrollment
строки (строки, содержащие значение первичного ключа этого учащегося во внешнем StudentID
ключевом столбце), свойство Student
навигации этой сущности Enrollments
будет содержать эти две Enrollment
сущности.
Свойства навигации обычно определяются как virtual
, чтобы они могли воспользоваться преимуществами определенных функций Entity Framework, таких как отложенная загрузка. (Отложенная загрузка будет описана далее в руководстве по чтению связанных данных далее в этой серии.
Если свойство навигации может содержать несколько сущностей (как в отношениях "многие ко многим" или "один ко многим"), оно должно иметь тип списка, допускающий добавление, удаление и обновление записей, такой как ICollection
.
Сущность регистрации
В папке Models создайте файл Enrollment.cs и замените существующий код следующим кодом:
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; }
}
}
Свойство Grade является перечислением. Знак вопроса после объявления типа Grade
указывает, что свойство Grade
допускает значение NULL. Оценка со значением NULL отличается от нулевой оценки. Значение NULL означает, что оценка не известна или еще не назначена.
Свойство StudentID
представляет собой внешний ключ. Ему соответствует свойство навигации Student
. Сущность Enrollment
связана с одной сущностью Student
, поэтому это свойство может содержать одну сущность Student
(в отличие от представленного ранее свойства навигации Student.Enrollments
, которое может содержать несколько сущностей Enrollment
).
Свойство CourseID
представляет собой внешний ключ. Ему соответствует свойство навигации Course
. Сущность Enrollment
связана с одной сущностью Course
.
Сущность Course
В папке Models создайте Course.cs, заменив существующий код следующим кодом:
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; }
}
}
Свойство Enrollments
является свойством навигации. Сущность Course
может быть связана с любым числом сущностей Enrollment
.
Мы расскажем больше о [DatabaseGenerated(DatabaseGeneratedOption. Атрибут None)] в следующем руководстве. Фактически, этот атрибут позволяет ввести первичный ключ для курса, а не использовать базу данных, чтобы создать его.
Создание контекста базы данных
Класс main, который координирует функциональные возможности Entity Framework для данной модели данных, является классом контекста базы данных. Этот класс создается путем наследования от класса System.Data.Entity.DbContext . В коде указываются сущности, которые включаются в модель данных. Также вы можете настроить реакцию платформы Entity Framework на некоторые события. В этом проекте соответствующий класс называется SchoolContext
.
Создайте папку с именем DAL (для уровня доступа к данным). В этой папке создайте файл класса с именем SchoolContext.cs и замените существующий код следующим кодом:
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>();
}
}
}
Этот код создает свойство DbSet для каждого набора сущностей. В терминологии Entity Framework набор сущностей обычно соответствует таблице базы данных, а сущность соответствует строке в таблице.
Оператор modelBuilder.Conventions.Remove
в методе OnModelCreating предотвращает множественное число имен таблиц. Если этого не сделать, созданные таблицы будут называться Students
, Courses
и Enrollments
. Вместо этого в таблицах будут Student
использоваться имена , Course
и Enrollment
. В среде разработчиков нет единого мнения о том, следует ли использовать имена таблиц во множественном числе. В этом руководстве используется единственная форма, но важно то, что вы можете выбрать любую форму, включив или опустив эту строку кода.
SQL Server Express LocalDB
LocalDB — это упрощенная версия ядра СУБД SQL Server Express, которая запускается по запросу и работает в пользовательском режиме. LocalDB выполняется в специальном режиме выполнения SQL Server Express, который позволяет работать с базами данных как с .mdf файлами. Как правило, файлы базы данных LocalDB хранятся в папке App_Data веб-проекта. Функция пользовательского экземпляра в SQL Server Express также позволяет работать с .mdf файлами, но эта функция экземпляра пользователя является устаревшей, поэтому для работы с файлами .mdf рекомендуется использовать LocalDB.
Как правило, SQL Server Express не используется для рабочих веб-приложений. LocalDB, в частности, не рекомендуется использовать в рабочей среде с веб-приложением, так как она не предназначена для работы с IIS.
В Visual Studio 2012 и более поздних версиях LocalDB устанавливается по умолчанию вместе с Visual Studio. В Visual Studio 2010 и более ранних версиях SQL Server Express (без LocalDB) устанавливается по умолчанию вместе с Visual Studio. Если вы используете Visual Studio 2010, его необходимо установить вручную.
В этом руководстве вы будете работать с LocalDB, чтобы базу данных можно было сохранить в папке App_Data в виде файла .mdf . Откройте корневой файлWeb.config и добавьте в коллекцию connectionStrings
новый строка подключения, как показано в следующем примере. (Обязательно обновите файлWeb.config в корневой папке проекта. Существует также 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" />
По умолчанию Entity Framework ищет строка подключения с именем того же, что и DbContext
класс (SchoolContext
для этого проекта). Добавленный строка подключения указывает базу данных LocalDB с именем ContosoUniversity.mdf, расположенную в папке App_Data. Дополнительные сведения см. в разделе SQL Server строки подключения для веб-приложений ASP.NET.
Указывать строка подключения не нужно. Если вы не предоставляете строка подключения, Entity Framework создаст его для вас, однако база данных может не находиться в папке App_data приложения. Сведения о том, где будет создана база данных, см. в разделе Code First to a New Database.
Коллекция connectionStrings
также имеет строка подключения с именем DefaultConnection
, которая используется для базы данных членства. В этом руководстве вы не будете использовать базу данных членства. Единственное различие между двумя строками подключения заключается в имени базы данных и значении атрибута name.
Настройка и выполнение первой миграции кода
При первом запуске разработки приложения модель данных часто меняется, и при каждом изменении модели она выходит из-за синхронизации с базой данных. Вы можете настроить Entity Framework для автоматического удаления и повторного создания базы данных при каждом изменении модели данных. Это не проблема на ранних этапах разработки, так как тестовые данные легко создать повторно, но после развертывания в рабочей среде обычно требуется обновить схему базы данных без удаления базы данных. Функция миграции позволяет Code First обновлять базу данных без удаления и повторного создания. В начале цикла разработки нового проекта может потребоваться использовать DropCreateDatabaseIfModelChanges для удаления, повторного создания и повторного заполнения базы данных при каждом изменении модели. Вы готовы к развертыванию приложения и можете преобразовать его в подход миграции. В этом руководстве будут использоваться только миграции. Дополнительные сведения см. в разделе серия Code First Migrations и миграции screencast.
Включение Code First Migrations
В меню Сервис выберите пункт Диспетчер пакетов NuGet , а затем — Консоль диспетчера пакетов.
В командной строке
PM>
введите следующую команду:enable-migrations -contexttypename SchoolContext
Эта команда создает папку Migrations в проекте ContosoUniversity и помещает в нее Configuration.cs файл, который можно изменить для настройки миграции.
Класс
Configuration
включает метод,Seed
который вызывается при создании базы данных и при каждом ее обновлении после изменения модели данных.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" } // ); // } }
Этот метод предназначен для
Seed
вставки тестовых данных в базу данных после ее создания или обновления.
Настройка метода seed
Метод Seed запускается, когда Code First Migrations создает базу данных и каждый раз при обновлении базы данных до последней миграции. Метод Seed предназначен для того, чтобы вы могли вставлять данные в таблицы, прежде чем приложение впервые обращается к базе данных.
В более ранних версиях Code First, до выпуска миграций, Seed
часто методы вставляли тестовые данные, так как при каждом изменении модели во время разработки базу данных приходилось полностью удалять и повторно создавать с нуля. При использовании Code First Migrations тестовые данные сохраняются после изменений базы данных, поэтому включать тестовые данные в метод Seed обычно не требуется. На самом деле, вы не хотите Seed
, чтобы метод вставлял тестовые данные, если вы будете использовать миграции для развертывания базы данных в рабочей среде, так как Seed
метод будет выполняться в рабочей среде. В этом случае требуется, Seed
чтобы метод вставлял в базу данных только данные, которые нужно вставить в рабочую среду. Например, может потребоваться, чтобы база данных включала в таблицу Department
фактические имена отделов, когда приложение станет доступным в рабочей среде.
В этом руководстве вы будете использовать миграции для развертывания, но ваш Seed
метод в любом случае будет вставлять тестовые данные, чтобы упростить представление о работе функциональных возможностей приложения без необходимости вручную вставлять большое количество данных.
Замените содержимое файла Configuration.cs приведенным ниже кодом, который загрузит тестовые данные в новую базу данных.
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(); } } }
Метод Seed принимает объект контекста базы данных в качестве входного параметра, а код в методе использует этот объект для добавления новых сущностей в базу данных. Для каждого типа сущности код создает коллекцию новых сущностей, добавляет их в соответствующее свойство DbSet , а затем сохраняет изменения в базе данных. Не нужно вызывать метод SaveChanges после каждой группы сущностей, как показано здесь, но это поможет найти источник проблемы при возникновении исключения во время записи кода в базу данных.
Некоторые операторы, которые вставляют данные, используют метод AddOrUpdate для выполнения операции upsert.
Seed
Так как метод выполняется при каждой миграции, вы не можете просто вставить данные, так как строки, которые вы пытаетесь добавить, уже будут там после первой миграции, в которой создается база данных. Операция upsert предотвращает ошибки, которые могут возникнуть при попытке вставить уже существующую строку, но переопределяет любые изменения данных, которые могли быть внесены во время тестирования приложения. Если тестовые данные находятся в некоторых таблицах, это может не произойти. В некоторых случаях при изменении данных во время тестирования требуется, чтобы изменения сохранялись после обновления базы данных. В этом случае требуется выполнить условную операцию вставки: вставить строку, только если она еще не существует. Метод Seed использует оба подхода.Первый параметр, передаваемый методу AddOrUpdate, указывает свойство для проверка, если строка уже существует. Для данных тестового учащегося, которые вы предоставляете, свойство можно использовать для этой цели,
LastName
так как каждая фамилия в списке уникальна:context.Students.AddOrUpdate(p => p.LastName, s)
В этом коде предполагается, что фамилии уникальны. При добавлении учащегося с повторяющимся именем вы получите следующее исключение при следующем выполнении миграции.
Последовательность содержит несколько элементов
Дополнительные сведения о методе см. в
AddOrUpdate
статье Использование метода AddOrUpdate для EF 4.3 в блоге Джули Лерман.Код, добавляющий
Enrollment
сущностиAddOrUpdate
, не использует метод . Он проверяет, существует ли сущность, и вставляет сущность, если она не существует. Этот подход сохраняет изменения, внесенные в оценку регистрации при выполнении миграции. Код циклически выполняется по каждому членуEnrollment
списка , и если регистрация не найдена в базе данных, он добавляет регистрацию в базу данных. При первом обновлении базы данных она будет пустой, поэтому она будет добавлять каждую регистрацию.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); } }
Сведения об отладке
Seed
метода и обработке избыточных данных, таких как два учащегося с именем "Александр Карсон", см. в статье Seeding and Debugging Entity Framework (EF) DBs в блоге Рика Андерсона.Выполните построение проекта.
Создание и выполнение первой миграции
В окне Консоль диспетчера пакетов введите следующие команды:
add-migration InitialCreate update-database
Команда
add-migration
добавляет в папку Migrations файл [DateStamp]_InitialCreate.cs , содержащий код, который создает базу данных. Первый параметр (InitialCreate)
используется для имени файла и может быть любым; обычно вы выбираете слово или фразу, которые обобщают действия, выполняемые в миграции. Например, последнюю миграцию можно назвать "AddDepartmentTable".Метод
Up
InitialCreate
класса создает таблицы базы данных, соответствующие наборам сущностей модели данных, иDown
метод удаляет их. Функция миграций вызывает методUp
, чтобы реализовать изменения модели данных для миграции. При вводе команды для отката обновления функция миграций вызывает методDown
. В следующем коде показано содержимоеInitialCreate
файла: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"); } } }
Команда
update-database
запускаетUp
метод для создания базы данных, а затем —Seed
метод для заполнения базы данных.
Теперь для вашей модели данных создана база данных SQL Server. Имя базы данных — ContosoUniversity, а файл .mdf находится в папке App_Data проекта, так как это указано в строка подключения.
Для просмотра базы данных в Visual Studio можно использовать server Обозреватель или SQL Server обозреватель объектов (SSOX). В этом руководстве используется серверная Обозреватель. В Visual Studio Express 2012 для Web Обозреватель сервера называется Обозреватель базы данных.
В меню Вид выберите сервер Обозреватель.
Щелкните значок Добавить подключение .
Если появится запрос в диалоговом окне Выбор источника данных, щелкните Microsoft SQL Server, а затем нажмите кнопку Продолжить.
В диалоговом окне Добавление подключения введите (localdb)\v11.0 в поле Имя сервера. В разделе Выберите или введите имя базы данных выберите ContosoUniversity.
Нажмите кнопку ОК.
Разверните узел SchoolContext , а затем — Таблицы.
Щелкните правой кнопкой мыши таблицу Student и выберите команду Показать данные таблицы , чтобы просмотреть созданные столбцы и строки, которые были вставлены в таблицу.
Создание контроллера и представлений учащихся
Следующим шагом является создание ASP.NET контроллера MVC и представлений в приложении, который может работать с одной из этих таблиц.
Чтобы создать контроллер, щелкните правой
Student
кнопкой мыши папку Контроллеры в Обозреватель решений, выберите Добавить, а затем — Контроллер. В диалоговом окне Добавление контроллера выберите следующие параметры и нажмите кнопку Добавить:Имя контроллера: StudentController.
Шаблон: контроллер MVC с действиями чтения и записи и представлениями с использованием Entity Framework.
Класс модели: Student (ContosoUniversity.Models). (Если вы не видите этот параметр в раскрывающемся списке, выполните сборку проекта и повторите попытку.)
Класс контекста данных: SchoolContext (ContosoUniversity.Models).
Представления: Razor (CSHTML). (Значение по умолчанию.)
Visual Studio открывает файл Controllers\StudentController.cs . Вы увидите, что создана переменная класса, которая создает экземпляр объекта контекста базы данных:
private SchoolContext db = new SchoolContext();
Метод
Index
действия получает список учащихся из набора сущностей Students , считываяStudents
свойство экземпляра контекста базы данных:public ViewResult Index() { return View(db.Students.ToList()); }
Представление Student\Index.cshtml отображает этот список в таблице:
<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> }
Нажмите клавиши CTRL+F5, чтобы запустить проект.
Перейдите на вкладку Учащиеся , чтобы просмотреть тестовые данные, вставленные методом
Seed
.
Соглашения
Объем кода, который необходимо написать, чтобы платформа Entity Framework могла создать полную базу данных, минимальный из-за использования соглашений или допущений, которые делает Entity Framework. Некоторые из них уже отмечены:
- В качестве имен таблиц используются во множественном числе имена классов сущностей.
- В качестве имен столбцов используются имена свойств сущностей.
- Свойства сущности с именем
ID
или classnameID
распознаются как свойства первичного ключа.
Вы видели, что соглашения можно переопределить (например, вы указали, что имена таблиц не должны быть во множественном числе), и вы узнаете больше о соглашениях и их переопределении в учебнике Создание более сложной модели данных далее в этой серии. Дополнительные сведения см. в разделе Соглашения Code First.
Сводка
Теперь вы создали простое приложение, которое использует Entity Framework и SQL Server Express для хранения и отображения данных. В следующем руководстве вы узнаете, как выполнять базовые операции CRUD (создание, чтение, обновление, удаление). Вы можете оставить отзыв в нижней части этой страницы. Сообщите нам, как вам понравилась эта часть руководства и как мы можем улучшить ее.
Ссылки на другие ресурсы Entity Framework можно найти в ASP.NET схеме содержимого доступа к данным.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по