Ereditarietà dei tipi complessi in OData v4 con API Web ASP.NET

di Microsoft

In base alla specifica OData v4, un tipo complesso può ereditare da un altro tipo complesso. Un tipo complesso è un tipo strutturato senza una chiave. L'API Web OData 5.3 supporta l'ereditarietà dei tipi complessa.

Questo argomento illustra come creare un modello di dati di entità (EDM) con tipi di ereditarietà complessi.

Versioni software usate nell'esercitazione

  • API Web OData 5.3
  • OData v4

Gerarchia dei modelli

Per illustrare l'ereditarietà dei tipi complessi, si userà la gerarchia di classi seguente.

Diagramma della gerarchia del modello, che illustra l'ereditarietà dei tipi per la classe 'window' con frecce che puntano ai relativi elementi figlio.

Shape è un tipo complesso astratto. Rectangle, Trianglee Circle sono tipi complessi derivati da Shapee RoundRectangle derivano da Rectangle. Window è un tipo di entità e contiene un'istanza Shape di .

Ecco le classi CLR che definiscono questi tipi.

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
}

Compilare il modello EDM

Per creare l'EDM, è possibile usare ODataConventionModelBuilder, che deduce le relazioni di ereditarietà dai tipi CLR.

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

È anche possibile compilare in modo esplicito EDM usando ODataModelBuilder. Questo richiede più codice, ma offre un maggiore controllo sull'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();
}

Questi due esempi creano lo stesso schema EDM.

Documento metadati

Di seguito è riportato il documento dei metadati OData, che mostra l'ereditarietà dei tipi complessi.

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

Dal documento di metadati è possibile osservare che:

  • Il Shape tipo complesso è astratto.
  • Il Rectangletipo , Trianglee Circle complesso ha il tipo di Shapebase .
  • Il RoundRectangle tipo ha il tipo di Rectanglebase .

Cast di tipi complessi

Il cast su tipi complessi è ora supportato. Ad esempio, la query seguente esegue il cast di un Shape oggetto a un oggetto Rectangle.

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

Ecco il payload della risposta:

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