다음을 통해 공유


ASP.NET MVC 애플리케이션에서 Entity Framework를 사용하여 정렬, 필터링 및 페이징(10개 중 3개)

작성자: Tom Dykstra

Contoso University 샘플 웹 애플리케이션은 Entity Framework 5 Code First 및 Visual Studio 2012를 사용하여 ASP.NET MVC 4 애플리케이션을 만드는 방법을 보여 줍니다. 자습서 시리즈에 대한 정보는 시리즈의 첫 번째 자습서를 참조하세요.

참고

resolve 수 없는 문제가 발생하면 완료된 장을 다운로드하고 문제를 재현해 보세요. 일반적으로 코드를 완료된 코드와 비교하여 문제에 대한 솔루션을 찾을 수 있습니다. 몇 가지 일반적인 오류 및 해결 방법은 오류 및 해결 방법을 참조하세요.

이전 자습서에서는 엔터티에 대한 기본 CRUD 작업에 대한 웹 페이지 집합을 Student 구현했습니다. 이 자습서에서는 학생 인덱스 페이지에 정렬, 필터링 및 페이징 기능을 추가합니다. 단순 그룹화를 수행하는 페이지도 만듭니다.

다음 그림에서는 작업이 완료되었을 때 페이지 모양을 보여 줍니다. 열 제목은 해당 열로 정렬하기 위해 사용자가 클릭할 수 있는 링크입니다. 열 제목을 반복해서 클릭하면 오름차순 및 내림차순으로 정렬 순서가 토글됩니다.

Students_Index_page_with_paging

학생 인덱스 페이지에 정렬을 추가하려면 컨트롤러의 메서드를 IndexStudent 변경하고 인덱스 보기에 Student 코드를 추가합니다.

Index 메서드에 정렬 기능 추가

Controllers\StudentController.cs에서 메서드를 Index 다음 코드로 바꿉니다.

public ActionResult Index(string sortOrder)
{
   ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name_desc" : "";
   ViewBag.DateSortParm = sortOrder == "Date" ? "Date_desc" : "Date";
   var students = from s in db.Students
                  select s;
   switch (sortOrder)
   {
      case "Name_desc":
         students = students.OrderByDescending(s => s.LastName);
         break;
      case "Date":
         students = students.OrderBy(s => s.EnrollmentDate);
         break;
      case "Date_desc":
         students = students.OrderByDescending(s => s.EnrollmentDate);
         break;
      default:
         students = students.OrderBy(s => s.LastName);
         break;
   }
   return View(students.ToList());
}

이 코드는 URL의 쿼리 문자열에서 sortOrder 매개 변수를 받습니다. 쿼리 문자열 값은 ASP.NET MVC에서 작업 메서드에 대한 매개 변수로 제공됩니다. 매개 변수는 "Name" 또는 "Date" 문자열이며 필요에 따라 밑줄과 내림차순을 지정하는 문자열 "desc"가 옵니다. 기본 정렬 순서는 오름차순입니다.

인덱스 페이지를 처음 요청하면 쿼리 문자열은 없습니다. 학생은 에 의해 LastName오름차순으로 표시됩니다. 이는 문의 가을 통과 사례에 switch 의해 설정된 기본값입니다. 사용자가 열 제목 하이퍼링크를 클릭하면 쿼리 문자열에 해당 sortOrder 값이 제공됩니다.

뷰가 적절한 쿼리 문자열 값으로 열 머리글 하이퍼링크를 구성할 수 있도록 두 ViewBag 변수가 사용됩니다.

ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name_desc" : "";
ViewBag.DateSortParm = sortOrder == "Date" ? "Date_desc" : "Date";

이것은 3개로 구성된 문입니다. 첫 번째는 매개 변수가 null이거나 비어 ViewBag.NameSortParm 있는 경우 sortOrder 를 "name_desc"로 설정하도록 지정하고, 그렇지 않으면 빈 문자열로 설정해야 합니다. 이러한 두 문을 사용하면 뷰에서 다음과 같이 열 제목 하이퍼링크를 설정할 수 있습니다.

현재 정렬 순서 성 하이퍼링크 날짜 하이퍼링크
성 오름차순 descending ascending
성 내림차순 ascending ascending
날짜 오름차순 ascending descending
날짜 내림차순 ascending ascending

메서드는 LINQ to Entities 사용하여 정렬 기준 열을 지정합니다. 코드는 문 앞에 IQueryable 변수를 switch 만들고 문에서 switch 수정하고 문 다음에 메서드를 ToListswitch 호출합니다. IQueryable 변수를 작성하고 수정하면 데이터베이스에 쿼리가 보내지지 않습니다. 와 같은 ToList메서드를 호출하여 개체를 IQueryable 컬렉션으로 변환할 때까지 쿼리가 실행되지 않습니다. 따라서 이 코드는 문까지 실행되지 않는 단일 쿼리를 생성합니다 return View .

Views\Student\Index.cshtml에서 제목 행의 <tr><th> 요소를 강조 표시된 코드로 바꿉니다.

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            @Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm })
        </th>
        <th>First Name
        </th>
        <th>
            @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm })
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {

이 코드는 속성의 ViewBag 정보를 사용하여 적절한 쿼리 문자열 값으로 하이퍼링크를 설정합니다.

페이지를 실행하고 등록 날짜 열 머리글을 클릭하여 정렬이 작동하는지 확인합니다.

Contoso University Students 인덱스 페이지를 보여 주는 스크린샷 열 머리글은 성, 이름 및 등록 날짜입니다.

제목을 클릭하면 학생이 내림차순으로 표시됩니다.

내림차순으로 표시된 학생 목록이 있는 Contoso University Students 인덱스 페이지를 보여 주는 스크린샷

학생 인덱스 페이지에 검색 상자 추가

학생 인덱스 페이지에 필터링을 추가하려면 뷰에 텍스트 상자와 [제출] 단추를 추가하고 Index 메서드에 해당 변경 내용을 적용합니다. 텍스트 상자를 통해 이름 및 성 필드에서 검색할 문자열을 입력할 수 있습니다.

Index 메서드에 필터링 기능 추가

Controllers\StudentController.cs에서 메서드를 Index 다음 코드로 바꿉니다(변경 내용이 강조 표시됨).

public ViewResult Index(string sortOrder, string searchString)
{
    ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
    ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
    var students = from s in db.Students
                   select s;
    if (!String.IsNullOrEmpty(searchString))
    {
        students = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())
                               || s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
    }
    switch (sortOrder)
    {
        case "name_desc":
            students = students.OrderByDescending(s => s.LastName);
            break;
        case "Date":
            students = students.OrderBy(s => s.EnrollmentDate);
            break;
        case "date_desc":
            students = students.OrderByDescending(s => s.EnrollmentDate);
            break;
        default:
            students = students.OrderBy(s => s.LastName);
            break;
    }

    return View(students.ToList());
}

searchString 매개 변수를 Index 메서드에 추가했습니다. 또한 이름 또는 성에 검색 문자열이 포함된 학생만 선택하는 절을 LINQ 문 where 에 추가했습니다. 검색 문자열 값은 인덱스 보기에 추가할 텍스트 상자에서 수신됩니다. where 절을 추가하는 문은 검색할 값이 있는 경우에만 실행됩니다.

참고

대부분의 경우 Entity Framework 엔터티 집합에서 또는 메모리 내 컬렉션에서 확장 메서드로 동일한 메서드를 호출할 수 있습니다. 결과는 일반적으로 동일하지만 경우에 따라 다를 수 있습니다. 예를 들어 메서드의 Contains .NET Framework 구현은 빈 문자열을 전달할 때 모든 행을 반환하지만 SQL Server Compact 4.0에 대한 Entity Framework 공급자는 빈 문자열에 대해 0개의 행을 반환합니다. 따라서 예제의 코드(문 안에 if 문을 배치Where)를 사용하면 모든 버전의 SQL Server 동일한 결과를 얻을 수 있습니다. 또한 메서드의 Contains .NET Framework 구현은 기본적으로 대/소문자를 구분하는 비교를 수행하지만 Entity Framework SQL Server 공급자는 기본적으로 대/소문자를 구분하지 않는 비교를 수행합니다. 따라서 테스트를 명시적으로 대/소문자를 구분하지 않도록 메서드를 호출 ToUpper 하면 나중에 리포지토리를 사용하도록 코드를 변경할 때 결과가 변경되지 않습니다. 그러면 개체 대신 IQueryable 컬렉션이 반환 IEnumerable 됩니다. (IEnumerable 컬렉션에서 Contains 메서드를 호출하면 .NET Framework 구현을 가져오고 IQueryable 개체에서 호출하면 데이터베이스 공급자 구현을 가져옵니다.)

Students 인덱스 뷰에 검색 상자 추가

Views\Student\Index.cshtml에서 열린 table 태그 바로 앞에 강조 표시된 코드를 추가하여 캡션, 텍스트 상자 및 검색 단추를 만듭니다.

<p>
    @Html.ActionLink("Create New", "Create")
</p>

@using (Html.BeginForm())
{
    <p>
        Find by name: @Html.TextBox("SearchString")  
        <input type="submit" value="Search" /></p>
}

<table>
    <tr>

페이지를 실행하고 검색 문자열을 입력한 다음 검색 을 클릭하여 필터링이 작동하는지 확인합니다.

Students_Index_page_with_search_box

URL에 "an" 검색 문자열이 포함되어 있지 않습니다. 즉, 이 페이지에 책갈피를 지정하면 책갈피를 사용할 때 필터링된 목록이 표시되지 않습니다. 자습서의 뒷부분에서 필터 조건에 쿼리 문자열을 사용하도록 검색 단추를 변경합니다.

학생 인덱스 페이지에 페이징 추가

학생 인덱스 페이지에 페이징을 추가하려면 먼저 PagedList.Mvc NuGet 패키지를 설치합니다. 그런 다음 메서드를 추가로 변경하고 보기에 Index 페이징 링크를 Index 추가합니다. PagedList.Mvc 는 ASP.NET MVC에 대한 많은 좋은 페이징 및 정렬 패키지 중 하나이며, 여기에 사용하는 것은 다른 옵션에 대한 권장 사항이 아니라 예제로만 사용됩니다. 다음 그림에서는 페이징 링크를 보여 줍니다.

페이징 링크를 보여 주는 학생 인덱스 페이지의 스크린샷.

PagedList.MVC NuGet 패키지 설치

NuGet PagedList.Mvc 패키지는 PagedList 패키지를 종속성으로 자동으로 설치합니다. PagedList 패키지는 및 IEnumerable 컬렉션에 PagedList 대한 컬렉션 형식 및 확장 메서드를 IQueryable 설치합니다. 확장 메서드는 또는 IEnumerable에서 컬렉션 IQueryablePagedList 단일 데이터 페이지를 만들고 컬렉션은 페이징을 PagedList 용이하게 하는 몇 가지 속성과 메서드를 제공합니다. PagedList.Mvc 패키지는 페이징 단추를 표시하는 페이징 도우미를 설치합니다.

도구 메뉴에서 NuGet 패키지 관리자를 선택한 다음, 솔루션용 NuGet 패키지 관리를 선택합니다.

NuGet 패키지 관리 대화 상자의 왼쪽에 있는 온라인 탭을 클릭한 다음 검색 상자에 "paged"를 입력합니다. PagedList.Mvc 패키지가 표시되면 설치를 클릭합니다.

N u GET 패키지 관리 대화 상자를 보여 주는 스크린샷 페이지가 지정된 단어로 채워진 온라인 탭과 검색 창이 강조 표시됩니다. 페이징된 목록 패키지가 선택되어 있습니다.

프로젝트 선택 상자에서 확인을 클릭합니다.

프로젝트 선택 대화 상자를 보여 주는 스크린샷 OK 단추가 선택되어 있습니다.

인덱스 메서드에 페이징 기능 추가

Controllers\StudentController.cs에서 네임스페이 usingPagedList 스에 대한 문을 추가합니다.

using PagedList;

Index 메서드를 다음 코드로 바꿉니다.

public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
{
   ViewBag.CurrentSort = sortOrder;
   ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
   ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

   if (searchString != null)
   {
      page = 1;
   }
   else
   {
      searchString = currentFilter;
   }

   ViewBag.CurrentFilter = searchString;

   var students = from s in db.Students
                  select s;
   if (!String.IsNullOrEmpty(searchString))
   {
      students = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())
                             || s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
   }
   switch (sortOrder)
   {
      case "name_desc":
         students = students.OrderByDescending(s => s.LastName);
         break;
      case "Date":
         students = students.OrderBy(s => s.EnrollmentDate);
         break;
      case "date_desc":
         students = students.OrderByDescending(s => s.EnrollmentDate);
         break;
      default:  // Name ascending 
         students = students.OrderBy(s => s.LastName);
         break;
   }

   int pageSize = 3;
   int pageNumber = (page ?? 1);
   return View(students.ToPagedList(pageNumber, pageSize));
}

이 코드는 page 다음과 같이 매개 변수, 현재 정렬 순서 매개 변수 및 현재 필터 매개 변수를 메서드 서명에 추가합니다.

public ActionResult Index(string sortOrder, string currentFilter, string searchString, int? page)

페이지가 처음 표시되거나 사용자가 페이징 또는 정렬 링크를 클릭하지 않으면 모든 매개 변수가 Null이 됩니다. 페이징 링크를 클릭하면 변수에 page 표시할 페이지 번호가 포함됩니다.

A ViewBag 페이징하는 동안 정렬 순서를 동일하게 유지하려면 페이징 링크에 포함되어야 하므로 속성은 현재 정렬 순서를 사용하여 뷰를 제공합니다.

ViewBag.CurrentSort = sortOrder;

또 다른 속성인 ViewBag.CurrentFilter는 현재 필터 문자열을 사용하여 뷰를 제공합니다. 이 값은 페이징 중 필터 설정을 유지하기 위해 페이징 링크에 포함되어야 하며 페이지를 다시 표시할 때 텍스트 상자에 복원되어야 합니다. 페이징 중에 검색 문자열이 변경되면 새 필터로 인해 다른 데이터가 표시될 수 있으므로 페이지는 1로 재설정되어야 합니다. 텍스트 상자에 값을 입력하고 제출 단추를 누르면 검색 문자열이 변경됩니다. 이 경우 매개 변수는 searchString null이 아닙니다.

if (searchString != null)
        page = 1;
else
    searchString = currentFilter;

메서드 ToPagedList 의 끝에서 students 개체의 확장 메서드는 학생 IQueryable 쿼리를 페이징을 지원하는 컬렉션 형식의 단일 학생 페이지로 변환합니다. 그런 다음 학생의 단일 페이지가 보기로 전달됩니다.

int pageSize = 3;
int pageNumber = (page ?? 1);
return View(students.ToPagedList(pageNumber, pageSize));

ToPagedList 메서드는 페이지 번호를 사용합니다. 두 개의 물음표는 null 병합 연산자를 나타냅니다. Null 병합 연산자는 nullable 형식의 기본값을 정의합니다. (page ?? 1) 식은 값이 있는 경우 page 값을 반환하고 page가 Null이면 1일 반환합니다.

Views\Student\Index.cshtml에서 기존 코드를 다음 코드로 바꿉니다.

@model PagedList.IPagedList<ContosoUniversity.Models.Student>
@using PagedList.Mvc; 
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />

@{
    ViewBag.Title = "Students";
}

<h2>Students</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
@using (Html.BeginForm("Index", "Student", FormMethod.Get))
{
    <p>
        Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)  
        <input type="submit" value="Search" />
    </p>
}
<table>
<tr>
    <th></th>
    <th>
        @Html.ActionLink("Last Name", "Index", new { sortOrder=ViewBag.NameSortParm, currentFilter=ViewBag.CurrentFilter })
    </th>
    <th>
        First Name
    </th>
    <th>
        @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm, currentFilter = ViewBag.CurrentFilter })
    </th>
</tr>

@foreach (var item in Model) {
    <tr>
        <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>
        <td>
            @Html.DisplayFor(modelItem => item.LastName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.FirstMidName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EnrollmentDate)
        </td>
    </tr>
}

</table>
<br />
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

@Html.PagedListPager( Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter }) )

페이지 맨 위에 @model 문은 뷰가 List 개체 대신 PagedList 개체를 가져오는 것을 지정합니다.

에 대한 PagedList.Mvc 문은 using 페이징 단추에 대한 MVC 도우미에 대한 액세스를 제공합니다.

코드는 FormMethod.Get을 지정할 수 있는 BeginForm의 오버로드를 사용합니다.

@using (Html.BeginForm("Index", "Student", FormMethod.Get))
{
    <p>
        Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)  
        <input type="submit" value="Search" />
    </p>
}

기본 BeginForm 은 POST를 사용하여 양식 데이터를 제출합니다. 즉, 매개 변수는 URL이 아닌 HTTP 메시지 본문에 쿼리 문자열로 전달됩니다. HTTP GET을 지정하면 폼 데이터가 URL에 쿼리 문자열로 전달되고 이를 통해 사용자는 URL을 책갈피로 지정할 수 있습니다. HTTP GET 사용에 대한 W3C 지침은 작업이 업데이트되지 않을 때 GET을 사용해야 한다고 지정합니다.

텍스트 상자는 현재 검색 문자열로 초기화되므로 새 페이지를 클릭하면 현재 검색 문자열을 볼 수 있습니다.

Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)

열 머리글 링크는 쿼리 문자열을 사용하여 현재 검색 문자열을 컨트롤러에 전달하므로 사용자가 필터 결과 내에서 정렬할 수 있습니다.

@Html.ActionLink("Last Name", "Index", new { sortOrder=ViewBag.NameSortParm, currentFilter=ViewBag.CurrentFilter })

현재 페이지와 총 페이지 수가 표시됩니다.

Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

표시할 페이지가 없으면 "페이지 0/0"이 표시됩니다. (이 경우 페이지 번호는 1 Model.PageCount 이고 는 0이므로 페이지 수보다 큽니다Model.PageNumber.)

페이징 단추는 도우미에 PagedListPager 의해 표시됩니다.

@Html.PagedListPager( Model, page => Url.Action("Index", new { page }) )

도우미는 PagedListPager URL 및 스타일 지정을 포함하여 사용자 지정할 수 있는 다양한 옵션을 제공합니다. 자세한 내용은 GitHub 사이트의 TroyGoode/PagedList 를 참조하세요.

페이지를 실행합니다.

학생 인덱스 페이지의 스크린샷

다른 정렬 순서의 페이징 링크를 클릭하여 페이징이 작동하는지 확인합니다. 그런 다음, 검색 문자열을 입력하고 페이징을 다시 시도하여 정렬 및 필터링을 통해 페이징이 제대로 작동하는지 확인합니다.

학생 인덱스 페이지를 보여 주는 스크린샷 이름별 찾기 검색 창에 을 입력하는 단어입니다.

학생 통계를 표시하는 정보 페이지 만들기

Contoso University 웹 사이트의 정보 페이지에는 각 등록 날짜에 등록된 학생 수가 표시됩니다. 여기에는 그룹화와 그룹에 대한 간단한 계산이 필요합니다. 이 작업을 수행하기 위해 다음을 수행합니다.

  • 뷰에 전달해야 하는 데이터에 대해 뷰 모델 클래스를 만듭니다.
  • 컨트롤러에서 About 메서드를 수정합니다 Home .
  • 보기를 수정합니다 About .

보기 모델 만들기

ViewModels 폴더를 만듭니다. 해당 폴더에서 클래스 파일 EnrollmentDateGroup.cs를 추가하고 기존 코드를 다음 코드로 바꿉니다.

using System;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.ViewModels
{
    public class EnrollmentDateGroup
    {
        [DataType(DataType.Date)]
        public DateTime? EnrollmentDate { get; set; }

        public int StudentCount { get; set; }
    }
}

홈 컨트롤러 수정

HomeController.cs에서 파일 맨 위에 다음 using 문을 추가합니다.

using ContosoUniversity.DAL;
using ContosoUniversity.ViewModels;

클래스의 여는 중괄호 바로 뒤에 데이터베이스 컨텍스트에 대한 클래스 변수를 추가합니다.

public class HomeController : Controller
{
    private SchoolContext db = new SchoolContext();

About 메서드를 다음 코드로 바꿉니다.

public ActionResult About()
{
    var data = from student in db.Students
               group student by student.EnrollmentDate into dateGroup
               select new EnrollmentDateGroup()
               {
                   EnrollmentDate = dateGroup.Key,
                   StudentCount = dateGroup.Count()
               };
    return View(data);
}

LINQ 문은 등록 날짜별로 학생 엔터티를 그룹화하고 각 그룹의 엔터티 수를 계산하며 결과를 EnrollmentDateGroup 뷰 모델 개체의 컬렉션에 저장합니다.

메서드를 추가합니다.Dispose

protected override void Dispose(bool disposing)
{
    db.Dispose();
    base.Dispose(disposing);
}

정보 뷰 수정

Views\Home\About.cshtml 파일의 코드를 다음 코드로 바꿉니다.

@model IEnumerable<ContosoUniversity.ViewModels.EnrollmentDateGroup>
           
@{
    ViewBag.Title = "Student Body Statistics";
}

<h2>Student Body Statistics</h2>

<table>
    <tr>
        <th>
            Enrollment Date
        </th>
        <th>
            Students
        </th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.EnrollmentDate)
        </td>
        <td>
            @item.StudentCount
        </td>
    </tr>
}
</table>

앱을 실행하고 정보 링크를 클릭합니다. 각 등록 날짜에 대한 학생 수가 테이블에 표시됩니다.

About_page

선택 사항: Windows Azure에 앱 배포

지금까지 애플리케이션은 개발 컴퓨터의 IIS Express 로컬로 실행되었습니다. 다른 사용자가 인터넷을 통해 사용할 수 있도록 하려면 웹 호스팅 공급자에 배포해야 합니다. 자습서의 이 선택적 섹션에서는 Windows Azure 웹 사이트에 배포합니다.

Code First 마이그레이션 사용하여 데이터베이스 배포

데이터베이스를 배포하려면 Code First 마이그레이션 사용합니다. Visual Studio에서 배포 설정을 구성하는 데 사용하는 게시 프로필을 만들 때 Code First 마이그레이션 실행(애플리케이션 시작 시 실행)이라는 레이블이 지정된 검사 상자를 선택합니다. 이 설정을 사용하면 Code First에서 이니셜라이저 클래스를 사용하도록 MigrateDatabaseToLatestVersion 배포 프로세스가 대상 서버에서 애플리케이션 Web.config 파일을 자동으로 구성합니다.

Visual Studio는 배포 프로세스 중에 데이터베이스를 사용하여 아무 작업도 수행하지 않습니다. 배포된 애플리케이션이 배포 후 처음으로 데이터베이스에 액세스하면 Code First는 데이터베이스를 자동으로 만들거나 데이터베이스 스키마를 최신 버전으로 업데이트합니다. 애플리케이션이 Migrations Seed 메서드를 구현하는 경우 데이터베이스를 만들거나 스키마가 업데이트된 후 메서드가 실행됩니다.

Migrations 메서드는 Seed 테스트 데이터를 삽입합니다. 프로덕션 환경에 배포하는 경우 프로덕션 데이터베이스에 삽입하려는 데이터만 삽입하도록 메서드를 변경 Seed 해야 합니다. 예를 들어 현재 데이터 모델에서는 실제 과정이지만 개발 데이터베이스에 가상의 학생이 있을 수 있습니다. 개발에서 둘 다 로드하는 메서드를 Seed 작성한 다음 프로덕션에 배포하기 전에 가상의 학생을 주석으로 처리할 수 있습니다. 또는 메서드를 Seed 작성하여 과정만 로드하고 애플리케이션의 UI를 사용하여 테스트 데이터베이스에 가상의 학생을 수동으로 입력할 수 있습니다.

Windows Azure 계정 가져오기

Windows Azure 계정이 필요합니다. 아직 없는 경우 몇 분 만에 평가판 계정을 만들 수 있습니다. 자세한 내용은 Windows Azure 평가판을 참조하세요.

Windows Azure에서 웹 사이트 및 SQL 데이터베이스 만들기

Windows Azure 웹 사이트는 공유 호스팅 환경에서 실행됩니다. 즉, 다른 Windows Azure 클라이언트와 공유되는 VM(가상 머신)에서 실행됩니다. 공유 호스팅 환경은 클라우드를 시작하는 저비용 방법입니다. 나중에 웹 트래픽이 증가하면 애플리케이션이 전용 VM에서 실행되어 요구에 맞게 확장될 수 있습니다. 더 복잡한 아키텍처가 필요한 경우 Windows Azure Cloud Service로 마이그레이션할 수 있습니다. 클라우드 서비스는 요구에 따라 구성할 수 있는 전용 VM에서 실행됩니다.

Windows Azure SQL Database는 SQL Server 기술을 기반으로 하는 클라우드 기반 관계형 데이터베이스 서비스입니다. SQL Server 사용하는 도구 및 애플리케이션도 SQL Database 작동합니다.

  1. Windows Azure 관리 포털의 왼쪽 탭에서 웹 사이트를클릭한 다음 새로 만들기를 클릭합니다.

    관리 포털의 새 단추

  2. 사용자 지정 만들기를 클릭합니다.

    새 대화 상자를 보여 주는 스크린샷 웹 사이트 및 사용자 지정 만들기 옵션이 강조 표시됩니다.

    새 웹 사이트 - 사용자 지정 만들기 마법사가 열립니다.

  3. 마법사의 새 웹 사이트 단계에서 애플리케이션의 고유 URL로 사용할 문자열을 URL 상자에 입력합니다. 전체 URL은 여기에 입력한 문자열과 텍스트 상자 옆에 표시되는 접미사로 구성됩니다. 그림에서는 "ConU"를 보여 주지만 해당 URL은 다른 URL을 선택해야 할 수 있습니다.

    관리 포털에서 데이터베이스로 만들기 링크

  4. 지역 드롭다운 목록에서 가까운 지역을 선택합니다. 이 설정은 웹 사이트에서 실행할 데이터 센터를 지정합니다.

  5. 데이터베이스 드롭다운 목록에서 무료 20MB SQL 데이터베이스 만들기를 선택합니다.

    웹 사이트 만들기 대화 상자를 보여 주는 스크린샷 데이터베이스 드롭다운 목록에서 무료 20M B S QL 데이터베이스를 선택합니다. 검사 표시 단추가 강조 표시됩니다.

  6. DB 연결 문자열 이름에서 SchoolContext를 입력합니다.

    웹 사이트 만들기 대화 상자를 보여 주는 스크린샷 학교 컨텍스트가 DB 연결 문자열 이름 텍스트 필드에 채워집니다. 검사 표시 단추가 강조 표시되어 있습니다.

  7. 상자 아래쪽의 오른쪽을 가리키는 화살표를 클릭합니다. 마법사가 데이터베이스 설정 단계로 이동합니다.

  8. 이름 상자에 ContosoUniversityDB를 입력합니다.

  9. 서버 상자에서 새 SQL Database 서버를 선택합니다. 또는 이전에 서버를 만든 경우 드롭다운 목록에서 해당 서버를 선택할 수 있습니다.

  10. 관리자 로그인 이름암호를 입력합니다. New SQL Database 서버를 선택한 경우 여기서 기존 이름과 암호를 입력하지 않고 나중에 데이터베이스에 액세스할 때 사용하기 위해 지금 정의하는 새 이름과 암호를 입력합니다. 이전에 만든 서버를 선택한 경우 해당 서버에 대한 자격 증명을 입력합니다. 이 자습서에서는 고급 검사 상자를 선택하지 않습니다. 고급 옵션을 사용하면 데이터베이스 데이터 정렬을 설정할 수 있습니다.

  11. 웹 사이트에 대해 선택한 것과 동일한 지역을 선택합니다.

  12. 상자 오른쪽 아래에 있는 검사 표시를 클릭하여 완료되었음을 나타냅니다.

    모든 설정이 선택되고 텍스트 필드에 샘플 암호가 포함된 데이터베이스 설정 지정 대화 상자를 보여 주는 스크린샷 검사 표시 단추가 강조 표시되어 있습니다.

    다음 이미지는 기존 SQL Server 및 로그인을 사용하는 방법을 보여줍니다.

    새 웹 사이트의 데이터베이스 설정 단계 - 데이터베이스를 사용하여 만들기 마법사

    관리 포털이 웹 사이트 페이지로 돌아오면 상태 열에 사이트가 만들어지고 있음을 보여 줍니다. 잠시 후(일반적으로 1분 미만) 상태 열에 사이트가 성공적으로 만들어졌음이 표시됩니다. 왼쪽 탐색 모음에서 계정에 있는 사이트 수가 웹 사이트 아이콘 옆에 표시되고 데이터베이스 수가 SQL Database 아이콘 옆에 표시됩니다.

Windows Azure에 애플리케이션 배포

  1. Visual Studio의 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 상황에 맞는 메뉴에서 게시를 선택합니다.

    프로젝트 상황에 맞는 메뉴의 게시

  2. 웹 게시 마법사의 프로필 탭에서 가져오기를 클릭합니다.

    게시 설정 가져오기

  3. Visual Studio에서 이전에 Windows Azure 구독을 추가하지 않은 경우 다음 단계를 수행합니다. 다음 단계에서는 Windows Azure 웹 사이트에서 가져오기 아래의 드롭다운 목록에 웹 사이트가 포함되도록 구독을 추가합니다.

    a. 게시 프로필 가져오기 대화 상자에서 Windows Azure 웹 사이트에서 가져오기를 클릭한 다음 Windows Azure 구독 추가를 클릭합니다.

    Windows Azure 구독 추가

    b. Windows Azure 구독 가져오기 대화 상자에서 구독 파일 다운로드를 클릭합니다.

    구독 파일 다운로드

    다. 브라우저 창에서 .publishsettings 파일을 저장합니다.

    .publishsettings 파일 다운로드

    경고

    보안 - publishsettings 파일에는 Windows Azure 구독 및 서비스를 관리하는 데 사용되는 자격 증명(인코딩되지 않음)이 포함되어 있습니다. 이 파일의 보안 모범 사례는 원본 디렉터리 외부(예: Libraries\Documents 폴더)에 임시로 저장한 다음 가져오기가 완료되면 삭제하는 것입니다. 파일에 대한 액세스 권한을 .publishsettings 얻는 악의적인 사용자는 Windows Azure 서비스를 편집, 만들기 및 삭제할 수 있습니다.

    d. Windows Azure 구독 가져오기 대화 상자에서 찾아보기를 클릭하고 .publishsettings 파일로 이동합니다.

    하위 다운로드

    e. 가져오기를 클릭합니다.

    가져오기

  4. 게시 프로필 가져오기 대화 상자에서 Windows Azure 웹 사이트에서 가져오기를 선택하고 드롭다운 목록에서 웹 사이트를 선택한 다음 확인을 클릭합니다.

    게시 프로필 가져오기

  5. 연결 탭에서 연결 유효성 검사를 클릭하여 설정이 올바른지 확인합니다.

    연결 유효성 검사

  6. 연결의 유효성을 검사하면 연결 유효성 검사 단추 옆에 녹색 검사 표시가 표시됩니다. 다음을 클릭합니다.

    연결의 유효성을 검사했습니다.

  7. SchoolContext에서 원격 연결 문자열 드롭다운 목록을 열고 만든 데이터베이스에 대한 연결 문자열을 선택합니다.

  8. Code First 마이그레이션 실행을 선택합니다(애플리케이션 시작 시 실행).

  9. 이 애플리케이션이 멤버 자격 데이터베이스를 사용하지 않으므로 UserContext(DefaultConnection)대해 런타임에 이 연결 문자열 사용을 선택 취소합니다.

    설정 탭

  10. 다음을 클릭합니다.

  11. 미리 보기 탭에서 미리 보기 시작을 클릭합니다.

    미리 보기 탭의 시작미리 보기 단추

    탭에는 서버에 복사할 파일 목록이 표시됩니다. 미리 보기를 표시하는 것은 애플리케이션을 게시할 필요가 없지만 알고 있어야 하는 유용한 함수입니다. 이 경우 표시되는 파일 목록을 사용하여 아무 작업도 수행할 필요가 없습니다. 다음에 이 애플리케이션을 배포할 때 변경된 파일만 이 목록에 포함됩니다.

    StartPreview 파일 출력

  12. 게시를 클릭합니다.
    Visual Studio는 Windows Azure 서버에 파일을 복사하는 프로세스를 시작합니다.

  13. 출력 창에 수행된 배포 작업이 표시되고 성공적인 배포 완료가 보고됩니다.

    성공적인 배포를 보고하는 출력 창

  14. 배포에 성공하면 기본 브라우저가 배포된 웹 사이트의 URL로 자동으로 열립니다.
    만든 애플리케이션이 이제 클라우드에서 실행되고 있습니다. 학생 탭을 클릭합니다.

    Students_index_page_with_paging

이 시점에서 Code First 마이그레이션 실행(앱 시작 시 실행)을 선택했기 때문에 Windows Azure SQL Database에서 SchoolContext 데이터베이스가 만들어졌습니다. 배포된 웹 사이트의 Web.config 파일이 변경되어 코드가 데이터베이스에서 데이터를 처음 읽거나 쓸 때 MigrateDatabaseToLatestVersion 이니셜라이저가 실행됩니다( 학생 탭을 선택할 때 발생).

데이터베이스를 최신 버전으로 마이그레이션이 강조 표시된 코드의 스크린샷

또한 배포 프로세스는 Code First 마이그레이션 데이터베이스 스키마를 업데이트하고 데이터베이스를 시드하는 데 사용할 새 연결 문자열(SchoolContext_DatabasePublish)을 만들었습니다.

Database_Publish 연결 문자열

DefaultConnection 연결 문자열은 멤버 자격 데이터베이스에 대한 것입니다(이 자습서에서는 사용하지 않음). SchoolContext 연결 문자열은 ContosoUniversity 데이터베이스용입니다.

배포된 버전의 Web.config 파일은ContosoUniversity\obj\Release\Package\PackageTmp\Web.config 컴퓨터에서 찾을 수 있습니다. FTP를 사용하여 배포된 Web.config 파일 자체에 액세스할 수 있습니다. 지침은 Visual Studio를 사용하여 웹 배포 ASP.NET: 코드 업데이트 배포를 참조하세요. "FTP 도구를 사용하려면 FTP URL, 사용자 이름 및 암호의 세 가지가 필요합니다."로 시작하는 지침을 따릅니다.

참고

웹앱은 보안을 구현하지 않으므로 URL을 찾은 사람은 누구나 데이터를 변경할 수 있습니다. 웹 사이트를 보호하는 방법에 대한 지침은 Membership, OAuth 및 SQL Database 사용하여 Windows Azure 웹 사이트에 보안 ASP.NET MVC 앱 배포를 참조하세요. Visual Studio에서 Windows Azure 관리 포털 또는 서버 Explorer 사용하여 사이트를 중지하여 다른 사용자가 사이트를 사용하지 못하도록 할 수 있습니다.

선택한 아래의 Windows Azure 웹 사이트 탭 및 Con U를 보여 주는 서버 Explorer 스크린샷 웹 사이트 중지 옵션이 있는 대화 상자 메뉴가 강조 표시됩니다.

코드 첫 번째 이니셜라이저

배포 섹션에서 MigrateDatabaseToLatestVersion 이니셜라이저가 사용되는 것을 보았습니다. Code First는 CreateDatabaseIfNotExists (기본값), DropCreateDatabaseIfModelChangesDropCreateDatabaseAlways를 포함하여 사용할 수 있는 다른 이니셜라이저도 제공합니다. 이니셜라이저는 DropCreateAlways 단위 테스트 조건을 설정하는 데 유용할 수 있습니다. 또한 고유한 이니셜라이저를 작성할 수 있으며 애플리케이션이 데이터베이스에서 읽거나 데이터베이스에 쓸 때까지 기다리지 않으려면 이니셜라이저를 명시적으로 호출할 수 있습니다. 이니셜라이저에 대한 포괄적인 설명은 프로그래밍 엔터티 프레임워크: Julie Lerman 및 Rowan Miller의 Code First 책 6장을 참조하세요.

요약

이 자습서에서는 데이터 모델을 만들고 기본 CRUD, 정렬, 필터링, 페이징 및 그룹화 기능을 구현하는 방법을 살펴보았습니다. 다음 자습서에서는 데이터 모델을 확장하여 고급 topics 살펴보기 시작합니다.

다른 Entity Framework 리소스에 대한 링크는 ASP.NET 데이터 액세스 콘텐츠 맵에서 찾을 수 있습니다.