2부: 도메인 모델 만들기

작성자: Rick Anderson

완료된 프로젝트 다운로드

모델 추가

Entity Framework에 접근하는 방법에는 다음 세 가지가 있습니다.

  • 데이터베이스 우선: 데이터베이스로 시작하고 Entity Framework에서 코드를 생성합니다.
  • 모델 우선: 시각적 모델로 시작하고 Entity Framework는 데이터베이스와 코드를 모두 생성합니다.
  • 코드 우선: 코드로 시작하고 Entity Framework에서 데이터베이스를 생성합니다.

코드 우선 접근 방식을 사용하므로 먼저 도메인 개체를 POTO(일반 오래된 CLR 개체)로 정의합니다. 코드 우선 접근 방식을 사용하면 도메인 개체는 트랜잭션 또는 지속성과 같은 데이터베이스 계층을 지원하기 위해 추가 코드가 필요하지 않습니다. (특히 EntityObject 클래스에서 상속할 필요가 없습니다.) 데이터 주석을 사용하여 Entity Framework에서 데이터베이스 스키마를 만드는 방법을 제어할 수 있습니다.

POTO는 데이터베이스 상태를 설명하는 추가 속성을 포함하지 않으므로 JSON 또는 XML로 쉽게 직렬화할 수 있습니다. 그러나 자습서의 뒷부분에서 볼 수 있듯이 항상 Entity Framework 모델을 클라이언트에 직접 노출해야 한다는 의미는 아닙니다.

다음 POCO를 만듭니다.

  • 제품
  • 주문
  • OrderDetail

각 클래스를 만들려면 솔루션 탐색기 Models 폴더를 마우스 오른쪽 단추로 클릭합니다. 상황에 맞는 메뉴에서 추가 를 선택한 다음 , 클래스를 선택합니다.

Models 폴더에 대한 솔루션 Explorer 메뉴의 스크린샷 추가 메뉴가 열려 있고 클래스 옵션이 강조 표시됩니다.

다음 구현을 사용하여 Product 클래스를 추가합니다.

namespace ProductStore.Models
{
    using System.ComponentModel.DataAnnotations;

    public class Product
    {
        [ScaffoldColumn(false)]
        public int Id { get; set; }
        [Required]
        public string Name { get; set; }
        public decimal Price { get; set; }
        public decimal ActualCost { get; set; }
    }
}

규칙에 따라 Entity Framework는 Id 속성을 기본 키로 사용하여 데이터베이스 테이블의 ID 열에 매핑합니다. 새 Product instance 만들 때 데이터베이스에서 값을 생성하므로 에 대한 Id값을 설정하지 않습니다.

ScaffoldColumn 특성은 편집기 양식을 생성할 때 속성을 건너뛰 Id 도록 ASP.NET MVC에 지시합니다. 필수 특성은 모델의 유효성을 검사하는 데 사용됩니다. 속성이 Name 비어 있지 않은 문자열이어야 한다고 지정합니다.

클래스를 추가합니다.Order

namespace ProductStore.Models
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;

    public class Order
    {
        public int Id { get; set; }
        [Required]
        public string Customer { get; set; }

        // Navigation property
        public  ICollection<OrderDetail> OrderDetails { get; set; }
    }
}

클래스를 추가합니다.OrderDetail

namespace ProductStore.Models
{
    public class OrderDetail
    {
        public int Id { get; set; }
        public int Quantity { get; set; }
        public int OrderId { get; set; }
        public int ProductId { get; set; }

        // Navigation properties
        public Product Product { get; set; }
        public Order Order { get; set; }
    }
}

외래 키 관계

주문에는 많은 주문 세부 정보가 포함되며 각 주문 세부 정보는 단일 제품을 참조합니다. 이러한 관계를 나타내기 위해 클래스는 OrderDetailProductId라는 OrderId 속성을 정의합니다. Entity Framework는 이러한 속성이 외래 키를 나타낸다는 것을 유추하고 외래 키 제약 조건을 데이터베이스에 추가합니다.

Orders, Products 및 OrderDetails 클래스에 대한 Visual Studio 메뉴의 스크린샷

OrderDetail 클래스에는 Order 관련 개체에 대한 참조를 포함하는 "탐색" 속성도 포함됩니다. 주문이 지정된 경우 탐색 속성에 따라 순서대로 제품으로 이동할 수 있습니다.

지금 프로젝트를 컴파일합니다. Entity Framework는 리플렉션을 사용하여 모델의 속성을 검색하므로 데이터베이스 스키마를 만들려면 컴파일된 어셈블리가 필요합니다.

Media-Type 포맷터 구성

미디어 형식 포맷터는 Web API가 HTTP 응답 본문을 작성할 때 데이터를 직렬화하는 개체입니다. 기본 제공 포맷터는 JSON 및 XML 출력을 지원합니다. 기본적으로 이러한 포맷터는 모두 모든 개체를 값으로 직렬화합니다.

개체 그래프에 순환 참조가 포함된 경우 값으로 직렬화하면 문제가 발생합니다. 각 클래스는 서로에 대한 참조를 Order 보유하기 때문에 및 OrderDetail 클래스의 경우와 정확히 일치합니다. 포맷터는 참조를 따르고 각 개체를 값으로 쓰고 원으로 이동합니다. 따라서 기본 동작을 변경해야 합니다.

솔루션 탐색기 App_Start 폴더를 확장하고 WebApiConfig.cs라는 파일을 엽니다. WebApiConfig 클래스에 다음 코드를 추가합니다.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        // New code:
        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling =
            Newtonsoft.Json.PreserveReferencesHandling.Objects;

        config.Formatters.Remove(config.Formatters.XmlFormatter);
    }
}

이 코드는 개체 참조를 유지하도록 JSON 포맷터를 설정하고 파이프라인에서 XML 포맷터를 완전히 제거합니다. (개체 참조를 유지하도록 XML 포맷터를 구성할 수 있지만 좀 더 작동하므로 이 애플리케이션에 JSON만 필요합니다. 자세한 내용은 순환 개체 참조 처리를 참조하세요.)