Héritage de type complexe dans OData v4 avec API Web ASP.NET

par Microsoft

Selon la spécification OData v4, un type complexe peut hériter d’un autre type complexe. (Un type complexe est un type structuré sans clé.) L’API web OData 5.3 prend en charge l’héritage de type complexe.

Cette rubrique montre comment créer un modèle de données d’entité (EDM) avec des types d’héritage complexes.

Versions logicielles utilisées dans le tutoriel

  • API web OData 5.3
  • OData v4

Hiérarchie de modèle

Pour illustrer l’héritage de type complexe, nous allons utiliser la hiérarchie de classes suivante.

Diagramme de la hiérarchie du modèle, illustrant l’héritage de type pour la classe « window » avec des flèches pointant vers ses enfants.

Shape est un type complexe abstrait. Rectangle, Triangleet Circle sont des types complexes dérivés de Shapeet RoundRectangle dérivent de Rectangle. Windowest un type d’entité et contient un Shape instance.

Voici les classes CLR qui définissent ces 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
}

Générer le modèle EDM

Pour créer l’EDM, vous pouvez utiliser ODataConventionModelBuilder, qui déduit les relations d’héritage des types CLR.

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

Vous pouvez également générer explicitement l’EDM à l’aide d’ODataModelBuilder. Cela nécessite plus de code, mais vous donne plus de contrôle sur l’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();
}

Ces deux exemples créent le même schéma EDM.

Document de métadonnées

Voici le document de métadonnées OData, montrant l’héritage de type complexe.

<?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>

Dans le document de métadonnées, vous pouvez voir ce qui suit :

  • Le Shape type complexe est abstrait.
  • Le Rectangletype complexe , Triangleet Circle ont le type Shapede base .
  • Le RoundRectangle type a le type Rectanglede base .

Cast de types complexes

Le cast sur des types complexes est désormais pris en charge. Par exemple, la requête suivante caste un Shape en .Rectangle

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

Voici la charge utile de réponse :

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