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.
Shape
è un tipo complesso astratto. Rectangle
, Triangle
e Circle
sono tipi complessi derivati da Shape
e 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
Rectangle
tipo ,Triangle
eCircle
complesso ha il tipo diShape
base . - Il
RoundRectangle
tipo ha il tipo diRectangle
base .
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
}