"
ASP.NET (snapshot 2017) Microsoft documentation and samples

Complex Type Inheritance in OData v4 with ASP.NET Web API

by Microsoft

According to the OData v4 specification, a complex type can inherit from another complex type. (A complex type is a structured type without a key.) Web API OData 5.3 supports complex type inheritance.

This topic shows how to build an entity data model (EDM) with complex inheritance types. For the complete source code, see OData Complex Type Inheritance Sample.

Software versions used in the tutorial

  • Web API OData 5.3
  • OData v4

Model Hierarchy

To illustrate complex type inheritance, we’ll use the following class hierarchy.

Shape is an abstract complex type. Rectangle, Triangle, and Circle are complex types derived from Shape, and RoundRectangle derives from Rectangle. Window is an entity type and contains a Shape instance.

Here are the CLR classes that define these types.

[!code-csharpMain]

   1:  public class Window
   2:  {
   3:      public int Id { get; set; }
   4:      public string Title { get; set; }
   5:      public Shape Shape { get; set; }
   6:  }
   7:   
   8:  public abstract class Shape
   9:  {
  10:      public bool HasBorder { get; set; }
  11:      public Color Color { get; set; }
  12:  }
  13:   
  14:  public class Rectangle : Shape
  15:  {
  16:      public Point P1 { get; set; }
  17:      public Point P2 { get; set; }
  18:      public Point P3 { get; set; }
  19:  }
  20:   
  21:  public class RoundRectangle : Rectangle
  22:  {
  23:      public double Round { get; set; }
  24:  }
  25:   
  26:  public class Triangle : Shape
  27:  {
  28:      public Point LeftTop { get; set; }
  29:      public int Height { get; set; }
  30:      public int Weight { get; set; }
  31:  }
  32:   
  33:  public class Circle : Shape
  34:  {
  35:      public Point Center { get; set; }
  36:      public int Radius { get; set; }
  37:  }
  38:   
  39:  public class Point
  40:  {
  41:      public int X { get; set; }
  42:      public int Y { get; set; }
  43:  }
  44:   
  45:  public enum Color
  46:  {
  47:      Red,
  48:      Blue,
  49:      Green,
  50:      Yellow
  51:  }

Build the EDM Model

To create the EDM, you can use ODataConventionModelBuilder, which infers the inheritance relationships from the CLR types.

[!code-csharpMain]

   1:  private IEdmModel GetEdmModel()
   2:  {
   3:      ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
   4:      builder.EntitySet<Window>("Windows");
   5:      return builder.GetEdmModel();
   6:  }

You can also build the EDM explicitly, using ODataModelBuilder. This takes more code, but gives you more control over the EDM.

[!code-csharpMain]

   1:  private IEdmModel GetExplicitEdmModel()
   2:  {
   3:    ODataModelBuilder builder = new ODataModelBuilder();
   4:   
   5:    EnumTypeConfiguration<Color> color = builder.EnumType<Color>();
   6:    color.Member(Color.Red);
   7:    color.Member(Color.Blue);
   8:    color.Member(Color.Green);
   9:    color.Member(Color.Yellow);
  10:   
  11:    ComplexTypeConfiguration<Point> point = builder.ComplexType<Point>();
  12:    point.Property(c => c.X);
  13:    point.Property(c => c.Y);
  14:   
  15:    ComplexTypeConfiguration<Shape> shape = builder.ComplexType<Shape>();
  16:    shape.EnumProperty(c => c.Color);
  17:    shape.Property(c => c.HasBorder);
  18:    shape.Abstract();
  19:   
  20:    ComplexTypeConfiguration<Triangle> triangle = builder.ComplexType<Triangle>();
  21:      triangle.ComplexProperty(c => c.P1);
  22:      triangle.ComplexProperty(c => c.P2);
  23:      triangle.ComplexProperty(c => c.P2);
  24:      triangle.DerivesFrom<Shape>();
  25:   
  26:      ComplexTypeConfiguration<Rectangle> rectangle = builder.ComplexType<Rectangle>();
  27:      rectangle.ComplexProperty(c => c.LeftTop);
  28:      rectangle.Property(c => c.Height);
  29:      rectangle.Property(c => c.Weight);
  30:      rectangle.DerivesFrom<Shape>();
  31:   
  32:    ComplexTypeConfiguration<RoundRectangle> roundRectangle = builder.ComplexType<RoundRectangle>();
  33:      roundRectangle.Property(c => c.Round);
  34:      roundRectangle.DerivesFrom<Rectangle>();
  35:   
  36:      ComplexTypeConfiguration<Circle> circle = builder.ComplexType<Circle>();
  37:      circle.ComplexProperty(c => c.Center);
  38:      circle.Property(c => c.Radius);
  39:      circle.DerivesFrom<Shape>();
  40:   
  41:      EntityTypeConfiguration<Window> window = builder.EntityType<Window>();
  42:      window.HasKey(c => c.Id);
  43:      window.Property(c => c.Title);
  44:      window.ComplexProperty(c => c.Shape);
  45:   
  46:      builder.EntitySet<Window>("Windows");
  47:      return builder.GetEdmModel();
  48:  }

These two examples create the same EDM schema.

Metadata Document

Here is the OData metadata document, showing complex type inheritance.

[!code-xmlMain]

   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
   3:    <edmx:DataServices>
   4:      <Schema Namespace="NS" xmlns="http://docs.oasis-open.org/odata/ns/edm">
   5:        <EntityType Name="Window">
   6:          <Key>
   7:            <PropertyRef Name="Id" />
   8:          </Key>
   9:          <Property Name="Id" Type="Edm.Int32" Nullable="false" />
  10:          <Property Name="Title" Type="Edm.String" />
  11:          <Property Name="Shape" Type="BookStore.Shape" />
  12:        </EntityType>
  13:        <ComplexType Name="Shape" Abstract="true">
  14:          <Property Name="HasBorder" Type="Edm.Boolean" Nullable="false" />
  15:          <Property Name="Color" Type="BookStore.Color" Nullable="false" />
  16:        </ComplexType>
  17:        <ComplexType Name="Circle" BaseType="BookStore.Shape">
  18:          <Property Name="Center" Type="BookStore.Point" />
  19:          <Property Name="Radius" Type="Edm.Int32" Nullable="false" />
  20:        </ComplexType>
  21:        <ComplexType Name="Point">
  22:          <Property Name="X" Type="Edm.Int32" Nullable="false" />
  23:          <Property Name="Y" Type="Edm.Int32" Nullable="false" />
  24:        </ComplexType>
  25:        <ComplexType Name="Rectangle" BaseType="BookStore.Shape">
  26:          <Property Name="LeftTop" Type="BookStore.Point" />
  27:          <Property Name="Height" Type="Edm.Int32" Nullable="false" />
  28:          <Property Name="Weight" Type="Edm.Int32" Nullable="false" />
  29:        </ComplexType>
  30:        <ComplexType Name="RoundRectangle" BaseType="BookStore.Rectangle">
  31:          <Property Name="Round" Type="Edm.Double" Nullable="false" />
  32:        </ComplexType>
  33:        <ComplexType Name="Triangle" BaseType="BookStore.Shape">
  34:          <Property Name="P1" Type="BookStore.Point" />
  35:          <Property Name="P2" Type="BookStore.Point" />
  36:          <Property Name="P3" Type="BookStore.Point" />
  37:        </ComplexType>
  38:        <EnumType Name="Color">
  39:          <Member Name="Red" Value="0" />
  40:          <Member Name="Blue" Value="1" />
  41:          <Member Name="Green" Value="2" />
  42:          <Member Name="Yellow" Value="3" />
  43:        </EnumType>
  44:      </Schema>
  45:      <Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
  46:        <EntityContainer Name="Container">
  47:          <EntitySet Name="Windows" EntityType="BookStore.Window" />
  48:        </EntityContainer>
  49:      </Schema>
  50:    </edmx:DataServices>
  51:  </edmx:Edmx>

From the metadata document, you can see that:

Casting Complex Types

Casting on complex types is now supported. For example, the following query casts a Shape to a Rectangle.

[!code-consoleMain]

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

Here’s the response payload:

[!code-consoleMain]

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



Comments ( )
Link to this page: //www.vb-net.com/AspNet-DocAndSamples-2017/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/complex-type-inheritance-in-odata-v4.htm
< THANKS ME>