Добавление нового поля
Примечание.
Обновленная версия этого руководства доступна здесь , используя последнюю версию Visual Studio. В новом руководстве используется ASP.NET Core MVC, что обеспечивает множество улучшений в этом руководстве.
В этом руководстве описывается модель MVC ASP.NET Core с контроллерами и представлениями. Razor Pages — это новая альтернатива в ASP.NET Core, модель программирования на основе страниц, которая упрощает создание веб-интерфейса и повышает производительность. Рекомендуем вам сначала попробовать изучить руководство по Razor Pages, прежде чем использовать версию для MVC. Руководство по Razor Pages:
- проще для выполнения;
- охватывает дополнительные возможности;
- Предпочтительный подход для разработки новых приложений.
В этом разделе вы будете использовать миграцию Entity Framework Code First Migrations для переноса некоторых изменений в классы моделей, чтобы изменения применялись к базе данных.
По умолчанию при использовании Entity Framework Code First для автоматического создания базы данных, как и ранее в этом руководстве, Code First добавляет таблицу в базу данных, чтобы отслеживать, синхронизирована ли схема базы данных с классами моделей, из них она была создана. Если они не синхронизированы, Entity Framework выдает ошибку. Это упрощает отслеживание проблем во время разработки, которые можно найти только (по неясным ошибкам) во время выполнения.
Настройка первых миграций кода для изменений модели
Перейдите к Обозреватель решений. Щелкните правой кнопкой мыши файл Movies.mdf и выберите "Удалить ", чтобы удалить базу данных фильмов. Если файл Movies.mdf не отображается, щелкните значок "Показать все файлы", показанный ниже в красном контуре.
Постройте приложение, чтобы убедиться в отсутствии ошибок.
В меню Сервис щелкните Диспетчер пакетов NuGet, а затем щелкните Консоль диспетчера пакетов.
В окне консоли диспетчер пакетов в строке PM>
запроса введите
Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext
Команда Enable-Migrations (показана выше) создает файл Configuration.cs в новой папке Migrations .
Visual Studio открывает файл Configuration.cs . Замените Seed
метод в файле Configuration.cs следующим кодом:
protected override void Seed(MvcMovie.Models.MovieDBContext context)
{
context.Movies.AddOrUpdate( i => i.Title,
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Price = 7.99M
},
new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},
new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},
new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
}
Наведите указатель мыши на красную линию Movie
в нижней области и щелкните ее, а затем щелкните Show Potential Fixes
с помощью MvcMovie.Models;
При этом добавляется следующая инструкция using:
using MvcMovie.Models;
Примечание.
Code First Migrations вызывает Seed
метод после каждой миграции (то есть вызов update-database в консоли диспетчер пакетов), и этот метод обновляет строки, которые уже вставлены, или вставляет их, если они еще не существуют.
Метод AddOrUpdate в следующем коде выполняет операцию upsert:
context.Movies.AddOrUpdate(i => i.Title,
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Rating = "PG",
Price = 7.99M
}
Так как метод Seed выполняется с каждой миграцией, вы не можете просто вставить данные, так как строки, которые вы пытаетесь добавить, уже будут там после первой миграции, которая создает базу данных. Операция upsert предотвращает ошибки, которые будут возникать при попытке вставить строку, которая уже существует, но переопределяет любые изменения данных, которые, возможно, были сделаны при тестировании приложения. С тестируемыми данными в некоторых таблицах может не потребоваться это сделать: в некоторых случаях при изменении данных при тестировании изменения будут оставаться после обновления базы данных. В этом случае необходимо выполнить условную операцию вставки: вставить строку только в том случае, если она еще не существует.
Первый параметр, переданный методу AddOrUpdate , указывает свойство, используемое для проверки наличия строки. Для данных тестового фильма, которые вы предоставляете, свойство можно использовать для этой цели, Title
так как каждое название в списке уникально:
context.Movies.AddOrUpdate(i => i.Title,
В этом коде предполагается, что заголовки уникальны. При добавлении повторяющегося заголовка вручную вы получите следующее исключение при следующем выполнении миграции.
Последовательность содержит несколько элементов
Дополнительные сведения о методе AddOrUpdate см. в разделе "Забота о методе EF 4.3 AddOrUpdate".
Нажмите клавиши CTRL-SHIFT-B, чтобы создать проект.(Если вы не создадите сборку на этом этапе, выполните следующие действия.
Следующим шагом является создание класса для начальной DbMigration
миграции. Эта миграция создает новую базу данных, поэтому вы удалили файл movie.mdf на предыдущем шаге.
В окне консоли диспетчер пакетов введите командуadd-migration Initial
, чтобы создать начальную миграцию. Имя "Initial" является произвольным и используется для имени созданного файла миграции.
Code First Migrations создает другой файл класса в папке Migrations (с именем {DateStamp}_Initial.cs ), а этот класс содержит код, который создает схему базы данных. Имя файла миграции предварительно исправлено с меткой времени для упорядочения. Изучите файл {DateStamp}_Initial.cs , в нем содержатся инструкции по созданию Movies
таблицы для базы данных Movie DB. При обновлении базы данных в приведенных ниже инструкциях этот файл {DateStamp}_Initial.cs будет запускаться и создавать схему базы данных. Затем метод Seed будет выполняться для заполнения базы данных тестовых данных.
В консоли диспетчер пакетов введите команду update-database
для создания базы данных и запуска Seed
метода.
Если возникает ошибка, указывающая, что таблица уже существует и не может быть создана, вероятно, это связано с тем, что вы запустили приложение после удаления базы данных и перед выполнением.update-database
В этом случае удалите файл Movies.mdf еще раз и повторите update-database
команду. Если вы по-прежнему получите ошибку, удалите папку миграции и содержимое, а затем начните с инструкций в верхней части этой страницы (то есть удалите файл Movies.mdf , а затем перейдите к enable-Migrations). Если по-прежнему возникает ошибка, откройте SQL Server обозреватель объектов и удалите базу данных из списка. Если отображается сообщение об ошибке "Не удается подключить файл .mdf в качестве базы данных", удалите свойство initial Catalog в составе строка подключения в файле web.config.
Запустите приложение и перейдите по URL-адресу /Movies . Отображаются начальные данные.
Добавление свойства Rating в модель Movie
Начните с добавления нового Rating
свойства в существующий Movie
класс. Откройте файл Models\Movie.cs и добавьте следующее Rating
свойство:
public string Rating { get; set; }
Полный Movie
класс теперь выглядит следующим образом:
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
public string Rating { get; set; }
}
Создайте приложение (CTRL+SHIFT+B).
Так как вы добавили новое поле в Movie
класс, необходимо также обновить список разрешений привязки, чтобы это новое свойство было включено. bind
Обновите атрибут и Edit
Create
методы действия, чтобы включить Rating
свойство:
[Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")]
Также необходимо обновить шаблоны представлений, чтобы реализовать отображение, создание и редактирование нового свойства Rating
в представлении браузера.
Откройте файл \Views\Movies\Index.cshtml и добавьте <th>Rating</th>
заголовок столбца сразу после столбца Price. Затем добавьте <td>
столбец в конце шаблона для отрисовки @item.Rating
значения. Ниже показано, как выглядит обновленный шаблон представления Index.cshtml :
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm("Index", "Movies", FormMethod.Get))
{
<p>
Genre: @Html.DropDownList("movieGenre", "All")
Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" />
</p>
}
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Rating)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
Затем откройте файл \Views\Movies\Create.cshtml и добавьте Rating
поле со следующей выделенной разметкой. Это отрисовывает текстовое поле, чтобы можно было указать оценку при создании нового фильма.
<div class="form-group">
@Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Rating, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Rating, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Теперь вы обновили код приложения для поддержки нового Rating
свойства.
Запустите приложение и перейдите по URL-адресу /Movies . Однако при этом вы увидите одну из следующих ошибок:
Модель, которая поддерживает контекст MovieDBContext, изменилась с момента создания базы данных. Рекомендуется использовать кодовые миграции для обновления базы данных (https://go.microsoft.com/fwlink/?LinkId=238269).
Эта ошибка возникает, так как обновленный Movie
класс модели в приложении теперь отличается от схемы Movie
таблицы существующей базы данных. (В таблице базы данных отсутствует столбец Rating
.)
Устранить эту ошибку можно несколькими способами:
- Можно с помощью Entity Framework автоматически удалить и повторно создать базу данных на основе новой схемы класса модели. Этот подход удобен на ранних стадиях цикла разработки, когда все действия осуществляются с тестовой базой данных. В этом случае развитие модели и схемы базы данных осуществляется одновременно. Однако недостатком является то, что вы теряете существующие данные в базе данных, поэтому вы не хотите использовать этот подход в рабочей базе данных! При разработке приложения часто используется инициализатор для автоматического заполнения базы тестовыми данными. Дополнительные сведения о инициализаторах баз данных Entity Framework см. в руководстве по ASP.NET MVC/Entity Framework.
- Можно явно изменить схему существующей базы данных в соответствии с новыми классами модели. Преимущество такого подхода состоит в том, что сохраняются все данные. Это изменение можно выполнить как вручную, так и с помощью соответствующего скрипта базы данных.
- Можно обновить схему базы данных с помощью Code First Migrations.
В этом руководстве используется Code First Migrations.
Обновите метод Seed таким образом, чтобы он предоставлял значение для нового столбца. Откройте файл Migrations\Configuration.cs и добавьте поле "Рейтинг" в каждый объект Movie.
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Rating = "PG",
Price = 7.99M
},
Создайте решение, а затем откройте окно консоли диспетчер пакетов и введите следующую команду:
add-migration Rating
Команда add-migration
сообщает платформе миграции, чтобы проверить текущую модель фильма с текущей схемой базы данных фильма и создать необходимый код для переноса базы данных в новую модель. Оценка имени является произвольной и используется для имени файла миграции. Полезно использовать понятное имя для шага миграции.
По завершении этой команды Visual Studio открывает файл класса, определяющий новый DbMigration
производный класс, и в методе Up
можно увидеть код, создающий новый столбец.
public partial class AddRatingMig : DbMigration
{
public override void Up()
{
AddColumn("dbo.Movies", "Rating", c => c.String());
}
public override void Down()
{
DropColumn("dbo.Movies", "Rating");
}
}
Создайте решение и введите update-database
команду в окне консоли диспетчер пакетов.
На следующем рисунке показаны выходные данные в окне консоли диспетчер пакетов (оценка метки даты будет отличаться).)
Повторно запустите приложение и перейдите по URL-адресу /Movies. Вы можете увидеть новое поле "Оценка".
Щелкните ссылку "Создать" , чтобы добавить новый фильм. Обратите внимание, что можно добавить оценку.
Нажмите кнопку Создать. Новый фильм, включая рейтинг, теперь отображается в списке фильмов:
Теперь, когда проект использует миграции, вам не потребуется удалить базу данных при добавлении нового поля или в противном случае обновить схему. В следующем разделе мы добавим изменения схемы и используем миграции для обновления базы данных.
Вы также должны добавить Rating
поле в шаблоны представлений "Изменить", "Сведения" и "Удалить".
Вы можете снова ввести команду update-database в окне консоли диспетчер пакетов и код миграции не будет выполняться, так как схема соответствует модели. Однако при выполнении метода update-database будет выполняться Seed
метод снова, и если вы изменили какие-либо данные начального значения, изменения будут потеряны, так как Seed
данные метода upserts. Дополнительные сведения о методе см. Seed
в руководстве по популярным ASP.NET MVC/Entity Framework Tom Dykstra.
В этом разделе вы узнали, как изменить объекты модели и синхронизировать базу данных с изменениями. Вы также узнали, как заполнить только что созданную базу данных примерами данных, чтобы вы могли попробовать сценарии. Это было просто краткое введение в код first, см . статью "Создание модели данных Entity Framework" для приложения MVC ASP.NET более полного руководства по теме. Далее давайте рассмотрим, как можно добавить более богатую логику проверки в классы моделей и включить применение некоторых бизнес-правил.