다음을 통해 공유


디자이너 TPH 상속

이 단계별 연습에서는 EF 디자이너(Entity Framework Designer)를 사용하여 개념적 모델에서 TPH(계층당 하나의 테이블) 상속을 구현하는 방법을 보여줍니다. TPH 상속에서는 하나의 데이터베이스 테이블을 사용하여 상속 계층 구조에 있는 모든 엔터티 형식의 데이터를 유지합니다.

이 연습에서는 Person 테이블을 Person(기본 형식), Student(Person에서 파생) 및 Instructor(Person에서 파생)의 세 가지 엔터티 형식에 매핑합니다. 데이터베이스에서 개념적 모델(Database First)을 만든 다음, EF 디자이너를 사용하여 TPH 상속을 구현하도록 모델을 변경합니다.

Model First를 사용하여 TPH 상속에 매핑할 수 있지만 복잡한 고유 데이터베이스 생성 워크플로를 작성해야 합니다. 그런 다음 이 워크플로를 EF 디자이너의 데이터베이스 생성 워크플로 속성에 할당합니다. 더 쉬운 대안은 Code First를 사용하는 것입니다.

기타 상속 옵션

TPT(형식당 하나의 테이블)는 데이터베이스의 별도 테이블이 상속에 참여하는 엔터티에 매핑되는 또 다른 유형의 상속입니다.  EF 디자이너를 사용하여 형식당 하나의 테이블 상속을 매핑하는 방법에 대한 자세한 내용은 EF 디자이너 TPT 상속을 참조하세요.

TPC(구체적 형식당 테이블) 상속 및 혼합 상속 모델은 Entity Framework 런타임에서 지원되지만 EF 디자이너에서는 지원되지 않습니다. TPC 또는 혼합 상속을 사용하려면 Code First를 사용하거나 EDMX 파일을 수동으로 편집하는 두 가지 옵션이 있습니다. EDMX 파일로 작업하도록 선택하면 매핑 세부 정보 창이 "안전 모드"로 전환되고 디자이너를 사용하여 매핑을 변경할 수 없습니다.

필수 조건

이 연습을 완료하려면 다음 사항이 필요합니다.

Project 설정

  • Visual Studio 2012를 엽니다.
  • 파일-> 새로 만들기 -> 프로젝트를 선택합니다.
  • 왼쪽 창에서 Visual C#을 클릭한 다음 콘솔 템플릿을 선택합니다.
  • 이름으로 TPHDBFirstSample을 입력합니다.
  • 확인을 선택합니다.

모델 만들기

  • 솔루션 탐색기에서 프로젝트 이름을 마우스 오른쪽 단추로 클릭하고 추가 -> 새 항목을 선택합니다.
  • 왼쪽 메뉴에서 데이터를 선택한 다음 템플릿 창에서 ADO.NET 엔터티 데이터 모델을 선택합니다.
  • 파일 이름에 TPHModel.edmx를 입력하고 추가를 클릭합니다.
  • 모델 콘텐츠 선택 대화 상자에서 데이터베이스에서 생성을 선택한 후 다음을 클릭합니다.
  • 새 연결을 클릭합니다. 연결 속성 대화 상자에서 서버 이름(예: (localdb)\mssqllocaldb)을 입력하고 인증 방법을 선택하고 데이터베이스 이름에 School을 입력한 다음 확인을 클릭합니다. 데이터 연결 선택 대화 상자가 데이터베이스 연결 설정으로 업데이트됩니다.
  • 데이터베이스 개체 선택 대화 상자의 테이블 노드 아래에서 Person 테이블을 선택합니다.
  • Finish를 클릭합니다.

모델을 편집하기 위한 디자인 화면을 제공하는 엔터티 디자이너가 표시됩니다. 데이터베이스 개체 선택 대화 상자에서 선택한 모든 개체가 모델에 추가됩니다.

이는 Person 테이블이 데이터베이스에서 보이는 방식입니다.

Person Table 

계층당 하나의 테이블 상속 구현

Person 테이블에는 "Student" 및 "Instructor"의 두 값 중 하나를 가질 수 있는 판별자 열이 있습니다. 값에 따라 Person 테이블은 Student 엔터티 또는 Instructor 엔터티에 매핑됩니다. Person 테이블에는 두 개의 열인 HireDateEnrollmentDate도 있으며, 여기에서 한 사람이 학생과 강사가 동시에 될 수 없기 때문에 null을 허용해야 합니다(적어도 이 연습에서는 아님).

새 엔터티 추가

  • 새 엔터티를 추가합니다. 이를 수행하려면 Entity Framework 디자이너의 디자인 화면의 빈 공간을 마우스 오른쪽 단추로 클릭하고 추가->엔터티를 선택합니다.
  • 엔터티 이름Instructor를 입력하고 기본 형식의 드롭다운 목록에서 Person을 선택합니다.
  • 확인을 클릭합니다.
  • 다른 새 엔터티를 추가합니다. 엔터티 이름Student를 입력하고 기본 형식의 드롭다운 목록에서 Person을 선택합니다.

두 개의 새 엔터티 형식이 디자인 화면에 추가되었습니다. 화살표가 새 엔터티 형식에서 엔터티 형식을 가리키며, 이는 Person이 새 엔터티 형식의 기본 형식임을 나타냅니다.

  • Person 엔터티의 HireDate 속성을 마우스 오른쪽 단추로 클릭합니다. 잘라내기를 선택하거나 Ctrl-X 키를 사용합니다.
  • Instructor 엔터티를 마우스 오른쪽 단추로 클릭하고 붙여넣기를 선택하거나 Ctrl-V 키를 사용합니다.
  • HireDate 속성을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.
  • 속성 창에서 null 허용 속성을 false로 설정합니다.
  • Person 엔터티의 EnrollmentDate 속성을 마우스 오른쪽 단추로 클릭합니다. 잘라내기를 선택하거나 Ctrl-X 키를 사용합니다.
  • Student 엔터티를 마우스 오른쪽 단추로 클릭하고 붙여넣기를 선택하거나 Ctrl-V 키를 사용합니다.
  • EnrollmentDate 속성을 선택하고 null 허용 속성을 false로 설정합니다.
  • Person 엔터티 형식을 선택합니다. 속성 창에서 해당 Abstract 속성을 true로 설정합니다.
  • Person에서 판별자 속성을 삭제합니다. 삭제해야 하는 이유는 다음 섹션에 설명되어 있습니다.

엔터티 매핑

  • Instructor를 마우스 오른쪽 단추로 클릭하고 테이블 매핑을 선택합니다. 매핑 세부 정보 창에서 Instructor 엔터티가 선택됩니다.

  • 매핑 세부 정보 창에서 <테이블 또는 뷰 추가>를 클릭합니다. <테이블 또는 뷰 추가> 필드는 선택한 엔터티를 매핑할 수 있는 테이블 또는 뷰의 드롭다운 목록이 됩니다.

  • 드롭다운 목록에서 Person을 선택합니다.

  • 매핑 세부 정보 창이 기본 열 매핑과 조건 추가 옵션으로 업데이트됩니다.

  • <조건 추가>를 클릭합니다. <조건 추가> 필드는 조건이 설정될 수 있는 열의 드롭다운 목록이 됩니다.

  • 드롭다운 목록에서 판별자를 선택합니다.

  • 매핑 세부 정보 창의 연산자 열에 있는 드롭다운 목록에서 =를 선택합니다.

  • 값/속성 열에 Instructor를 입력합니다. 최종 결과는 다음과 같아야 합니다.

    Mapping Details

  • Student 엔터티 형식에 대해 다음 단계를 반복하지만 조건을 Student 값과 동일하게 만듭니다.
    판별자 속성을 제거하려는 이유는 테이블 열을 두 번 이상 매핑할 수 없기 때문입니다. 이 열은 조건부 매핑에 사용되므로 속성 매핑에도 사용할 수 없습니다. 이는 조건이 Is Null 또는 Is Not Null 비교를 사용하는 경우 둘 다에 사용할 수 있는 유일한 방법입니다.

이제 계층당 하나의 테이블 상속이 구현되었습니다.

Final TPH

모델 사용

Main 메서드가 정의된 Program.cs 파일을 엽니다. 다음 코드를 Main 함수에 붙여 넣습니다. 이 코드는 세 개의 쿼리를 실행합니다. 첫 번째 쿼리는 모든 Person 개체를 다시 가져옵니다. 두 번째 쿼리는 OfType 메서드를 사용하여 Instructor 개체를 반환합니다. 세 번째 쿼리는 OfType 메서드를 사용하여 Student 개체를 반환합니다.

    using (var context = new SchoolEntities())
    {
        Console.WriteLine("All people:");
        foreach (var person in context.People)
        {
            Console.WriteLine("    {0} {1}", person.FirstName, person.LastName);
        }

        Console.WriteLine("Instructors only: ");
        foreach (var person in context.People.OfType<Instructor>())
        {
            Console.WriteLine("    {0} {1}", person.FirstName, person.LastName);
        }

        Console.WriteLine("Students only: ");
        foreach (var person in context.People.OfType<Student>())
        {
            Console.WriteLine("    {0} {1}", person.FirstName, person.LastName);
        }
    }