새 필드 추가
작성자: Rick Anderson
참고 항목
이 자습서의 업데이트된 버전은 최신 버전의 Visual Studio를 사용하여 여기에서 사용할 수 있습니다. 새 자습서에서는 ASP.NET Core MVC를 사용하여 이 자습서를 통해 많은 개선 사항을 제공합니다.
이 자습서에서는 컨트롤러와 보기를 통해 ASP.NET Core MVC에 설명합니다. Razor Pages는 웹 UI 빌드를 더 쉽고 생산성 있게 만드는 페이지 기반 프로그래밍 모델인 ASP.NET Core의 새로운 대안입니다. MVC 버전 이전의 Razor 페이지 자습서를 사용해 보는 것이 좋습니다. Razor 페이지 자습서:
- 자습서 내용을 좀 더 쉽게 진행할 수 있습니다.
- 더 많은 기능을 다룹니다.
- 새 앱 개발을 위한 기본 접근 방식입니다.
이 섹션에서는 Entity Framework Code First 마이그레이션 사용하여 변경 내용이 데이터베이스에 적용되도록 모델 클래스에 대한 일부 변경 내용을 마이그레이션합니다.
기본적으로 Entity Framework Code First를 사용하여 데이터베이스를 자동으로 만들 때 이 자습서의 앞부분에서 수행한 것처럼 Code First는 데이터베이스의 스키마가 생성된 모델 클래스와 동기화되어 있는지 여부를 추적하는 데 도움이 되는 테이블을 데이터베이스에 추가합니다. 동기화되지 않으면 Entity Framework에서 오류가 발생합니다. 이렇게 하면 런타임에 (모호한 오류로) 찾을 수 있는 개발 시 문제를 더 쉽게 추적할 수 있습니다.
모델 변경에 대한 Code First 마이그레이션 설정
솔루션 탐색기 이동합니다. Movies.mdf 파일을 마우스 오른쪽 단추로 클릭하고 삭제를 선택하여 동영상 데이터베이스를 제거합니다. Movies.mdf 파일이 표시되지 않으면 빨간색 윤곽선 아래에 표시된 모든 파일 표시 아이콘을 클릭합니다.
오류가 없는지 확인하기 위해 애플리케이션을 빌드합니다.
도구 메뉴에서 NuGet 패키지 관리자 클릭한 다음 콘솔을 패키지 관리자.
패키지 관리자 콘솔 창에서 프롬프트를 입력합니다PM>
.
Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext
Enable-Migrations 명령(위 그림 참조)은 새 마이그레이션 폴더에 Configuration.cs 파일을 만듭니다.
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
마우스를 가져 와서 MvcMovie.Models를 사용하여 클릭한 Show Potential Fixes
다음 클릭합니다.
이렇게 하면 다음 using 문이 추가되었습니다.
using MvcMovie.Models;
참고 항목
Code First 마이그레이션 모든 마이그레이션 후에 메서드를 호출 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 마이그레이션 다음에서 다른 클래스 파일을 만듭니다. 마이그레이션 폴더(이름이 {DateStamp}_Initial.cs)이고, 이 클래스에는 데이터베이스 스키마를 만드는 코드가 포함되어 있습니다. 마이그레이션 파일 이름은 순서를 지정하는 데 도움이 되는 타임스탬프로 미리 확정됩니다. {DateStamp}_Initial.cs 파일을 검사합니다. 여기에는 Movie DB에 대한 테이블을 만드는 Movies
지침이 포함되어 있습니다. 아래 지침에 따라 데이터베이스를 업데이트하면 이 {DateStamp}_Initial.cs 파일이 실행되고 DB 스키마가 생성됩니다. 그런 다음 Seed 메서드가 실행되어 DB를 테스트 데이터로 채웁다.
패키지 관리자 콘솔에서 데이터베이스를 만들고 메서드를 실행하는 명령을 update-database
입력합니다Seed
.
테이블이 이미 있고 만들 수 없음을 나타내는 오류가 발생하는 경우 데이터베이스를 삭제한 후 실행하기 전에 애플리케이션을 실행했기 update-database
때문일 수 있습니다. 이 경우 Movies.mdf 파일을 다시 삭제하고 명령을 다시 시도합니다update-database
. 여전히 오류가 발생하는 경우 마이그레이션 폴더 및 콘텐츠를 삭제한 다음 이 페이지의 맨 위에 있는 지침(Movies.mdf 파일을 삭제한 다음 Enable-Migrations로 진행)으로 시작합니다. 여전히 오류가 발생하면 SQL Server 개체 탐색기 열고 목록에서 데이터베이스를 제거합니다. ".mdf 파일을 데이터베이스로 연결할 수 없습니다"라는 오류가 표시되면 web.config 파일에서 연결 문자열 일부로 초기 카탈로그 속성을 제거합니다.
애플리케이션을 실행하고 /Movies URL로 이동합니다. 시드 데이터가 표시됩니다.
동영상 모델에 등급 속성 추가
먼저 기존 Movie
클래스에 새 Rating
속성을 추가합니다. 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
속성을 포함하도록 특성 Create
및 Edit
작업 메서드를 업데이트합니다Rating
.
[Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")]
브라우저 보기에서 새 Rating
속성을 표시, 작성 및 편집하기 위해 보기 템플릿도 업데이트해야 합니다.
\Views\Movies\Index.cshtml 파일을 열고 Price 열 바로 뒤의 열 머리글을 추가 <th>Rating</th>
합니다. 그런 다음 템플릿의 끝 부근에 열을 추가하여 <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
속성을 지원하도록 애플리케이션 코드를 업데이트했습니다.
애플리케이션을 실행하고 /Movies URL로 이동합니다. 하지만 이렇게 하면 다음 오류 중 하나가 표시됩니다.
데이터베이스를 만든 이후 'MovieDBContext' 컨텍스트를 지원하는 모델이 변경되었습니다. Code First 마이그레이션 사용하여 데이터베이스(https://go.microsoft.com/fwlink/?LinkId=238269)를 업데이트하는 것이 좋습니다.
이제 애플리케이션에서 업데이트 Movie
된 모델 클래스가 기존 데이터베이스 테이블의 Movie
스키마와 다르기 때문에 이 오류가 표시됩니다. (데이터베이스 테이블에 Rating
열이 없습니다.)
이 오류를 해결할 수 있는 몇 가지 방법이 있습니다.
- Entity Framework에서 새 모델 클래스 스키마에 따라 데이터베이스를 자동으로 삭제하고 다시 만들도록 합니다. 이 방법은 테스트 데이터베이스에서 활발한 개발을 수행할 때 개발 주기의 초기 단계에서 매우 편리하며 신속하게 모델 및 데이터베이스 스키마를 함께 개발할 수 있습니다. 하지만 단점은 데이터베이스에서 기존 데이터를 잃어버리므로 프로덕션 데이터베이스에서 이 방법을 사용하지 않으려는 것입니다. 테스트 데이터로 데이터베이스를 자동으로 시드하는 데 이니셜라이저를 사용하는 것은 종종 애플리케이션을 개발하는 효율적인 방법입니다. Entity Framework 데이터베이스 이니셜라이저에 대한 자세한 내용은 ASP.NET MVC/Entity Framework 자습서를 참조하세요.
- 모델 클래스와 일치하도록 기존 데이터베이스의 스키마를 명시적으로 수정합니다. 이 방법의 장점은 데이터가 유지된다는 점입니다. 이러한 변경을 수동으로 수행하거나 데이터베이스 변경 스크립트를 만들어 수행할 수 있습니다.
- Code First 마이그레이션을 사용하여 데이터베이스 스키마를 업데이트합니다.
이 자습서의 경우 Code First 마이그레이션을 사용합니다.
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
명령은 마이그레이션 프레임워크에 현재 동영상 DB 스키마를 사용하여 현재 동영상 모델을 검사하고 DB를 새 모델로 마이그레이션하는 데 필요한 코드를 만들도록 지시합니다. 이름 등급 은 임의이며 마이그레이션 파일의 이름을 지정하는 데 사용됩니다. 마이그레이션 단계에 의미 있는 이름을 사용하는 것이 유용합니다.
이 명령이 완료되면 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
합니다.
다음 이미지는 패키지 관리자 콘솔 창의 출력을 보여 줍니다(등급 앞에 오는 날짜 스탬프가 다릅니다.)
애플리케이션을 다시 실행하고 /Movies URL로 이동합니다. 새 등급 필드를 볼 수 있습니다.
새로 만들기 링크를 클릭하여 새 동영상을 추가합니다. 등급을 추가할 수 있습니다.
만들기를 클릭합니다. 등급을 포함한 새 영화가 이제 영화 목록에 표시됩니다.
이제 프로젝트에서 마이그레이션을 사용하므로 새 필드를 추가하거나 스키마를 업데이트할 때 데이터베이스를 삭제할 필요가 없습니다. 다음 섹션에서는 더 많은 스키마를 변경하고 마이그레이션을 사용하여 데이터베이스를 업데이트합니다.
또한 편집, 세부 정보 및 삭제 보기 템플릿에 필드를 추가 Rating
해야 합니다.
스키마가 모델과 일치하기 때문에 패키지 관리자 콘솔 창에 "update-database" 명령을 다시 입력할 수 있으며 마이그레이션 코드가 실행되지 않습니다. 그러나 "update-database"를 실행하면 메서드가 Seed
다시 실행되고 시드 데이터를 변경한 경우 메서드가 데이터를 upserts하기 때문에 Seed
변경 내용이 손실됩니다. Tom Dykstra의 인기 있는 ASP.NET MVC/Entity Framework 자습서에서 이 메서드에 대해 Seed
자세히 확인할 수 있습니다.
이 섹션에서는 모델 개체를 수정하고 데이터베이스를 변경 내용과 동기화된 상태로 유지하는 방법을 알아보았습니다. 시나리오를 사용해 볼 수 있도록 새로 만든 데이터베이스를 샘플 데이터로 채우는 방법도 알아보았습니다. 이 항목은 Code First에 대한 간단한 소개였습니다. 이 주제에 대한 자세한 자습서는 ASP.NET MVC 애플리케이션에 대한 Entity Framework 데이터 모델 만들기를 참조하세요. 다음으로, 모델 클래스에 보다 풍부한 유효성 검사 논리를 추가하고 일부 비즈니스 규칙을 적용할 수 있는 방법을 살펴보겠습니다.