ASP.NET 웹 API를 사용하여 OData v4의 복잡한 형식 상속Complex Type Inheritance in OData v4 with ASP.NET Web API

로 마이크로 소프트by Microsoft

OData v4 사양에따라 복소수 형식은 다른 복잡한 형식에서 상속될 수 있습니다.According to the OData v4 specification, a complex type can inherit from another complex type. (복잡한 complex 형식은 키가 없는 구조형입니다.) 웹 API OData 5.3은 복잡한 형식 상속을 지원합니다.(A complex type is a structured type without a key.) Web API OData 5.3 supports complex type inheritance.

이 항목에서는 복잡한 상속 형식을 사용하여 엔터티 데이터 모델(EDM)을 빌드하는 방법을 보여 주며 이 항목에서는This topic shows how to build an entity data model (EDM) with complex inheritance types. 전체 소스 코드는 OData 복합유형 상속 샘플을참조하십시오.For the complete source code, see OData Complex Type Inheritance Sample.

튜토리얼에 사용되는 소프트웨어 버전Software versions used in the tutorial

  • 웹 API OData 5.3Web API OData 5.3
  • OData v4OData v4

모델 계층 구조Model Hierarchy

복잡한 형식 상속을 설명하기 위해 다음 클래스 계층 구조를 사용합니다.To illustrate complex type inheritance, we'll use the following class hierarchy.

Shape는 추상 복합 유형입니다.Shape is an abstract complex type. Rectangle``CircleTriangle에서 Shape파생된 복합 형식이며 RoundRectangle 에서 Rectangle파생됩니다.Rectangle, Triangle, and Circle are complex types derived from Shape, and RoundRectangle derives from Rectangle. Window은 엔터티 유형이며 Shape 인스턴스를 포함합니다.Window is an entity type and contains a Shape instance.

다음은 이러한 형식을 정의하는 CLR 클래스입니다.Here are the CLR classes that define these types.

public class Window
{
    public int Id { get; set; }
    public string Title { get; set; }
    public Shape Shape { get; set; }
}

public abstract class Shape
{
    public bool HasBorder { get; set; }
    public Color Color { get; set; }
}

public class Rectangle : Shape
{
    public Point LeftTop { get; set; }
    public int Height { get; set; }
    public int Weight { get; set; }
}

public class RoundRectangle : Rectangle
{
    public double Round { get; set; }
}

public class Triangle : Shape
{
    public Point P1 { get; set; }
    public Point P2 { get; set; }
    public Point P3 { get; set; }
}

public class Circle : Shape
{
    public Point Center { get; set; }
    public int Radius { get; set; }
}

public class Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

public enum Color
{
    Red,
    Blue,
    Green,
    Yellow
}

EDM 모델 빌드Build the EDM Model

EDM을 만들려면 CLR 형식의 상속 관계를 유추하는 ODataConventionModelBuilder를사용할 수 있습니다.To create the EDM, you can use ODataConventionModelBuilder, which infers the inheritance relationships from the CLR types.

private IEdmModel GetEdmModel()
{
    ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<Window>("Windows");
    return builder.GetEdmModel();
}

ODataModelBuilder를사용하여 EDM을 명시적으로 빌드할 수도 있습니다.You can also build the EDM explicitly, using ODataModelBuilder. 이렇게 하면 더 많은 코드가 필요하지만 EDM을 보다 세한 제어할 수 있습니다.This takes more code, but gives you more control over the EDM.

private IEdmModel GetExplicitEdmModel()
{
  ODataModelBuilder builder = new ODataModelBuilder();

  EnumTypeConfiguration<Color> color = builder.EnumType<Color>();
  color.Member(Color.Red);
  color.Member(Color.Blue);
  color.Member(Color.Green);
  color.Member(Color.Yellow);

  ComplexTypeConfiguration<Point> point = builder.ComplexType<Point>();
  point.Property(c => c.X);
  point.Property(c => c.Y);

  ComplexTypeConfiguration<Shape> shape = builder.ComplexType<Shape>();
  shape.EnumProperty(c => c.Color);
  shape.Property(c => c.HasBorder);
  shape.Abstract();

  ComplexTypeConfiguration<Triangle> triangle = builder.ComplexType<Triangle>();
    triangle.ComplexProperty(c => c.P1);
    triangle.ComplexProperty(c => c.P2);
    triangle.ComplexProperty(c => c.P2);
    triangle.DerivesFrom<Shape>();

    ComplexTypeConfiguration<Rectangle> rectangle = builder.ComplexType<Rectangle>();
    rectangle.ComplexProperty(c => c.LeftTop);
    rectangle.Property(c => c.Height);
    rectangle.Property(c => c.Weight);
    rectangle.DerivesFrom<Shape>();

  ComplexTypeConfiguration<RoundRectangle> roundRectangle = builder.ComplexType<RoundRectangle>();
    roundRectangle.Property(c => c.Round);
    roundRectangle.DerivesFrom<Rectangle>();

    ComplexTypeConfiguration<Circle> circle = builder.ComplexType<Circle>();
    circle.ComplexProperty(c => c.Center);
    circle.Property(c => c.Radius);
    circle.DerivesFrom<Shape>();

    EntityTypeConfiguration<Window> window = builder.EntityType<Window>();
    window.HasKey(c => c.Id);
    window.Property(c => c.Title);
    window.ComplexProperty(c => c.Shape);

    builder.EntitySet<Window>("Windows");
    return builder.GetEdmModel();
}

이 두 예제는 동일한 EDM 스키마를 만듭니다.These two examples create the same EDM schema.

메타데이터 문서Metadata Document

다음은 복잡한 형식 상속을 보여 줄 수 있는 OData 메타데이터 문서입니다.Here is the OData metadata document, showing complex type inheritance.

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
  <edmx:DataServices>
    <Schema Namespace="NS" xmlns="http://docs.oasis-open.org/odata/ns/edm">
      <EntityType Name="Window">
        <Key>
          <PropertyRef Name="Id" />
        </Key>
        <Property Name="Id" Type="Edm.Int32" Nullable="false" />
        <Property Name="Title" Type="Edm.String" />
        <Property Name="Shape" Type="BookStore.Shape" />
      </EntityType>
      <ComplexType Name="Shape" Abstract="true">
        <Property Name="HasBorder" Type="Edm.Boolean" Nullable="false" />
        <Property Name="Color" Type="BookStore.Color" Nullable="false" />
      </ComplexType>
      <ComplexType Name="Circle" BaseType="BookStore.Shape">
        <Property Name="Center" Type="BookStore.Point" />
        <Property Name="Radius" Type="Edm.Int32" Nullable="false" />
      </ComplexType>
      <ComplexType Name="Point">
        <Property Name="X" Type="Edm.Int32" Nullable="false" />
        <Property Name="Y" Type="Edm.Int32" Nullable="false" />
      </ComplexType>
      <ComplexType Name="Rectangle" BaseType="BookStore.Shape">
        <Property Name="LeftTop" Type="BookStore.Point" />
        <Property Name="Height" Type="Edm.Int32" Nullable="false" />
        <Property Name="Weight" Type="Edm.Int32" Nullable="false" />
      </ComplexType>
      <ComplexType Name="RoundRectangle" BaseType="BookStore.Rectangle">
        <Property Name="Round" Type="Edm.Double" Nullable="false" />
      </ComplexType>
      <ComplexType Name="Triangle" BaseType="BookStore.Shape">
        <Property Name="P1" Type="BookStore.Point" />
        <Property Name="P2" Type="BookStore.Point" />
        <Property Name="P3" Type="BookStore.Point" />
      </ComplexType>
      <EnumType Name="Color">
        <Member Name="Red" Value="0" />
        <Member Name="Blue" Value="1" />
        <Member Name="Green" Value="2" />
        <Member Name="Yellow" Value="3" />
      </EnumType>
    </Schema>
    <Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
      <EntityContainer Name="Container">
        <EntitySet Name="Windows" EntityType="BookStore.Window" />
      </EntityContainer>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

메타데이터 문서에서 다음을 확인할 수 있습니다.From the metadata document, you can see that:

  • 복소수 형식은 Shape 추상적입니다.The Shape complex type is abstract.
  • Rectangle Triangle Circle 복합 형식에는 기본 형식이 Shape있습니다.The Rectangle, Triangle, and Circle complex type have the base type Shape.
  • RoundRectangle 형식에는 기본 형식이 Rectangle있습니다.The RoundRectangle type has the base type Rectangle.

주조 복합 유형Casting Complex Types

이제 복잡한 형식에 대한 캐스팅이 지원됩니다.Casting on complex types is now supported. 예를 들어 다음 쿼리는 Shape Rectanglea를 에 캐스팅합니다.For example, the following query casts a Shape to a Rectangle.

GET ~/odata/Windows(1)/Shape/NS.Rectangle/LeftTop

응답 페이로드는 다음과 같습니다.Here's the response payload:

{ 
   "@odata.context":"http://localhost/odata/$metadata#Windows(1)/Shape/NS.Rectangle/LeftTop",
    "X":100,"Y":100
}