Procédure : définir un modèle avec l'héritage TPH (table par hiérarchie) (Entity Framework)
Cette rubrique décrit comment créer manuellement un modèle conceptuel ayant l'héritage TPH (table par hiérarchie). L'héritage TPH (table par hiérarchie) utilise une table de base de données pour gérer les données de tous les types d'entité d'une hiérarchie d'héritage.
Remarque : |
---|
La méthode recommandée pour définir un modèle avec l'héritage TPT (table par type) est d'utiliser ADO.NET Entity Data Model Tools.Pour plus d'informations, consultez Walkthrough: Mapping Inheritance - Table-per-Hierarchy. |
Les principales étapes pour définir manuellement un modèle avec l'héritage TPH (table par hiérarchie) sont les suivantes :
Définissez un jeu d'entités dans le modèle conceptuel qui contiendra le type d'entité de base et les types dérivés. Pour plus d'informations, consultez Élément EntitySet (CSDL).
Définissez des types d'entité dérivés dans le modèle conceptuel à l'aide de l'attribut BaseType et définissez uniquement des propriétés non héritées sur les types dérivés. Pour plus d'informations, consultez Élément EntityType (CSDL).
Choisissez une colonne dans la table de base de données sous-jacente dont la valeur sera utilisée pour distinguer le type de base des types dérivés. Par exemple, si une table Employee a une colonne EmployeeType avec une valeur entière, la valeur de cette colonne peut être utilisée pour distinguer si un type d'entité de base Employee est l'un des types d'entité dérivés suivants : HourlyEmployee ou SalariedEmployee. Pour plus d'informations, consultez l'exemple suivant.
La colonne de discriminateur est mappée dans le cadre d'une condition, donc aucune propriété ne peut correspondre aux types d'entité dans la hiérarchie. L'exception à cette règle est lorsque la condition utilise une comparaison Is Null ou Is Not Null. Dans ce cas, la colonne de discriminateur peut avoir une propriété correspondante sur un type d'entité.
Si la colonne de discriminateur peut avoir plus de deux valeurs (type entier, par exemple), la colonne doit être Nullable ou avoir une valeur par défaut. Cela garantit que lorsqu'un type nouveau est créé et enregistré dans la base de données, la colonne peut être Null ou avoir une valeur.
Les conditions doivent être utilisées pour mapper chaque type dérivé dans la hiérarchie ; elles peuvent être utilisées pour mapper le type de base. Si le type de base est abstrait, aucun mappage n'est permis ni aucune condition.
Mappez le type d'entité de base et les types dérivés dans le même élément EntitySetMapping en MSL (Mapping Specification Language). Mappez des propriétés héritées aux colonnes de table, le cas échéant. Utilisez la syntaxe
IsTypeOf
lors de la définition de la valeur de l'attribut TypeName sur les types dérivés. Utilisez une condition de mappage pour distinguer les types dans la hiérarchie. Pour plus d'informations, consultez Élément EntitySetMapping (MSL) et Élément Condition (MSL).
L'exemple suivant suppose que vous avez installé l'exemple de base de données School et que vous avez configuré manuellement votre projet pour qu'il utilise Entity Framework . Pour plus d'informations, consultez Création de l'exemple de base de données School (Démarrage rapide d'Entity Framework) et Configuration d'Entity Framework (Tâches Entity Framework).
Pour créer le modèle de stockage
Ajoutez à votre projet le fichier XML suivant et nommez-le
AdventureWorks.ssdl
.<?xml version="1.0" encoding="utf-8" ?> <Schema Namespace="AdventureWorksModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="https://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="https://schemas.microsoft.com/ado/2009/02/edm/ssdl"> <EntityContainer Name="AdventureWorksModelStoreContainer"> <EntitySet Name="Product" EntityType="AdventureWorksModel.Store.Product" store:Type="Tables" Schema="Production" /> </EntityContainer> <EntityType Name="Product"> <Key> <PropertyRef Name="ProductID" /> </Key> <Property Name="ProductID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="50" /> <Property Name="ProductNumber" Type="nvarchar" Nullable="false" MaxLength="25" /> <Property Name="MakeFlag" Type="bit" Nullable="false" /> <Property Name="FinishedGoodsFlag" Type="bit" Nullable="false" /> <Property Name="Color" Type="nvarchar" MaxLength="15" /> <Property Name="SafetyStockLevel" Type="smallint" Nullable="false" /> <Property Name="ReorderPoint" Type="smallint" Nullable="false" /> <Property Name="StandardCost" Type="money" Nullable="false" /> <Property Name="ListPrice" Type="money" Nullable="false" /> <Property Name="Size" Type="nvarchar" MaxLength="5" /> <Property Name="SizeUnitMeasureCode" Type="nchar" MaxLength="3" /> <Property Name="WeightUnitMeasureCode" Type="nchar" MaxLength="3" /> <Property Name="Weight" Type="decimal" Precision="8" Scale="2" /> <Property Name="DaysToManufacture" Type="int" Nullable="false" /> <Property Name="ProductLine" Type="nchar" MaxLength="2" /> <Property Name="Class" Type="nchar" MaxLength="2" /> <Property Name="Style" Type="nchar" MaxLength="2" /> <Property Name="ProductSubcategoryID" Type="int" /> <Property Name="ProductModelID" Type="int" /> <Property Name="SellStartDate" Type="datetime" Nullable="false" /> <Property Name="SellEndDate" Type="datetime" /> <Property Name="DiscontinuedDate" Type="datetime" /> <Property Name="rowguid" Type="uniqueidentifier" Nullable="false" /> <Property Name="ModifiedDate" Type="datetime" Nullable="false" /> </EntityType> </Schema>
Pour créer le modèle conceptuel
Ajoutez à votre projet le fichier XML suivant et nommez-le
AdventureWorks.csdl
. Notez les points suivants :Un seul jeu d'entités, Products, est défini pour les deux types d'entité Product et DiscontinuedProduct.
Le type d'entité DiscontinuedProduct est un type dérivé comme indiqué par l'attribut
BaseType
dans sa définition.Les propriétés définies sur le type d'entité DiscontinuedProduct sont uniquement des propriétés non héritées.
La colonne MakeFlag dans le modèle de stockage (voir le fichier
AdventureWorks.ssdl
ci-dessus) n'apparaît pas comme une propriété sur le type de base ou le type dérivé. La valeur de cette colonne sera utilisée pour distinguer les types dans la hiérarchie, car elle est mappée dans le cadre d'une condition (voir le fichierAdventureWorks.msl
ci-dessous).
Remarque : Si la colonne est utilisée dans une condition Is Null ou Is Not Null, alors la propriété correspondante peut apparaître sur un type d'entité.
<?xml version="1.0" encoding="utf-8" ?>
<Schema Namespace="AdventureWorksModel" Alias="Self"
xmlns:annotation="https://schemas.microsoft.com/ado/2009/02/edm/annotation"
xmlns="https://schemas.microsoft.com/ado/2008/09/edm">
<EntityContainer Name="AdventureWorksEntities" annotation:LazyLoadingEnabled="true">
<EntitySet Name="Products" EntityType="AdventureWorksModel.Product" />
</EntityContainer>
<EntityType Name="Product">
<Key>
<PropertyRef Name="ProductID" />
</Key>
<Property Type="Int32" Name="ProductID" Nullable="false" />
<Property Type="String" Name="Name" Nullable="false" MaxLength="50"
FixedLength="false" Unicode="true" />
<Property Type="String" Name="ProductNumber" Nullable="false" MaxLength="25"
FixedLength="false" Unicode="true" />
<Property Type="Boolean" Name="FinishedGoodsFlag" Nullable="false" />
<Property Type="String" Name="Color" MaxLength="15" FixedLength="false"
Unicode="true" />
<Property Type="Int16" Name="SafetyStockLevel" Nullable="false" />
<Property Type="Int16" Name="ReorderPoint" Nullable="false" />
<Property Type="Decimal" Name="StandardCost" Nullable="false"
Precision="19" Scale="4" />
<Property Type="Decimal" Name="ListPrice" Nullable="false"
Precision="19" Scale="4" />
<Property Type="String" Name="Size" MaxLength="5" FixedLength="false"
Unicode="true" />
<Property Type="String" Name="SizeUnitMeasureCode" MaxLength="3"
FixedLength="true" Unicode="true" />
<Property Type="String" Name="WeightUnitMeasureCode" MaxLength="3"
FixedLength="true" Unicode="true" />
<Property Type="Decimal" Name="Weight" Precision="8" Scale="2" />
<Property Type="Int32" Name="DaysToManufacture" Nullable="false" />
<Property Type="String" Name="ProductLine" MaxLength="2"
FixedLength="true" Unicode="true" />
<Property Type="String" Name="Class" MaxLength="2" FixedLength="true"
Unicode="true" />
<Property Type="String" Name="Style" MaxLength="2" FixedLength="true"
Unicode="true" />
<Property Type="Int32" Name="ProductSubcategoryID" />
<Property Type="Int32" Name="ProductModelID" />
<Property Type="DateTime" Name="SellStartDate" Nullable="false" />
<Property Type="DateTime" Name="SellEndDate" />
<Property Type="Guid" Name="rowguid" Nullable="false" />
<Property Type="DateTime" Name="ModifiedDate" Nullable="false" />
</EntityType>
<EntityType Name="DiscontinuedProduct" BaseType="AdventureWorksModel.Product" >
<Property Type="DateTime" Name="DiscontinuedDate" />
</EntityType>
</Schema>
Pour définir le mappage entre le modèle conceptuel et le modèle de stockage.
Ajoutez à votre projet le fichier XML suivant et nommez-le
AdventureWorks.msl
. Notez les points suivants :Les mappages des types d'entité DiscontinuedProduct et Product sont définis dans le même élément EntitySetMapping.
Les propriétés héritées pour DiscontinuedProduct sont mappées aux colonnes correspondantes dans la table de base de données sous-jacente.
La syntaxe
IsTypeOf
est utilisée pour indiquer le type du type DiscontinuedProduct dérivé.La colonne de discriminateur, MakeFlag, est mappée dans un élément Condition pour chaque type d'entité dans la hiérarchie.
<?xml version="1.0" encoding="utf-8" ?> <Mapping Space="C-S" xmlns="https://schemas.microsoft.com/ado/2008/09/mapping/cs"> <EntityContainerMapping StorageEntityContainer="AdventureWorksModelStoreContainer" CdmEntityContainer="AdventureWorksEntities"> <EntitySetMapping Name="Products"> <EntityTypeMapping TypeName="AdventureWorksModel.Product"> <MappingFragment StoreEntitySet="Product"> <ScalarProperty Name="ProductID" ColumnName="ProductID" /> <ScalarProperty Name="ModifiedDate" ColumnName="ModifiedDate" /> <ScalarProperty Name="rowguid" ColumnName="rowguid" /> <ScalarProperty Name="SellEndDate" ColumnName="SellEndDate" /> <ScalarProperty Name="SellStartDate" ColumnName="SellStartDate" /> <ScalarProperty Name="ProductModelID" ColumnName="ProductModelID" /> <ScalarProperty Name="ProductSubcategoryID" ColumnName="ProductSubcategoryID" /> <ScalarProperty Name="Style" ColumnName="Style" /> <ScalarProperty Name="Class" ColumnName="Class" /> <ScalarProperty Name="ProductLine" ColumnName="ProductLine" /> <ScalarProperty Name="DaysToManufacture" ColumnName="DaysToManufacture" /> <ScalarProperty Name="Weight" ColumnName="Weight" /> <ScalarProperty Name="WeightUnitMeasureCode" ColumnName="WeightUnitMeasureCode" /> <ScalarProperty Name="SizeUnitMeasureCode" ColumnName="SizeUnitMeasureCode" /> <ScalarProperty Name="Size" ColumnName="Size" /> <ScalarProperty Name="ListPrice" ColumnName="ListPrice" /> <ScalarProperty Name="StandardCost" ColumnName="StandardCost" /> <ScalarProperty Name="ReorderPoint" ColumnName="ReorderPoint" /> <ScalarProperty Name="SafetyStockLevel" ColumnName="SafetyStockLevel" /> <ScalarProperty Name="Color" ColumnName="Color" /> <ScalarProperty Name="FinishedGoodsFlag" ColumnName="FinishedGoodsFlag" /> <ScalarProperty Name="ProductNumber" ColumnName="ProductNumber" /> <ScalarProperty Name="Name" ColumnName="Name" /> <Condition ColumnName="MakeFlag" Value="0" /> </MappingFragment> </EntityTypeMapping> <EntityTypeMapping TypeName="IsTypeOf(AdventureWorksModel.DiscontinuedProduct)"> <MappingFragment StoreEntitySet="Product"> <ScalarProperty Name="ModifiedDate" ColumnName="ModifiedDate" /> <ScalarProperty Name="rowguid" ColumnName="rowguid" /> <ScalarProperty Name="SellEndDate" ColumnName="SellEndDate" /> <ScalarProperty Name="SellStartDate" ColumnName="SellStartDate" /> <ScalarProperty Name="ProductModelID" ColumnName="ProductModelID" /> <ScalarProperty Name="ProductSubcategoryID" ColumnName="ProductSubcategoryID" /> <ScalarProperty Name="Style" ColumnName="Style" /> <ScalarProperty Name="Class" ColumnName="Class" /> <ScalarProperty Name="ProductLine" ColumnName="ProductLine" /> <ScalarProperty Name="DaysToManufacture" ColumnName="DaysToManufacture" /> <ScalarProperty Name="Weight" ColumnName="Weight" /> <ScalarProperty Name="WeightUnitMeasureCode" ColumnName="WeightUnitMeasureCode" /> <ScalarProperty Name="SizeUnitMeasureCode" ColumnName="SizeUnitMeasureCode" /> <ScalarProperty Name="Size" ColumnName="Size" /> <ScalarProperty Name="ListPrice" ColumnName="ListPrice" /> <ScalarProperty Name="StandardCost" ColumnName="StandardCost" /> <ScalarProperty Name="ReorderPoint" ColumnName="ReorderPoint" /> <ScalarProperty Name="SafetyStockLevel" ColumnName="SafetyStockLevel" /> <ScalarProperty Name="Color" ColumnName="Color" /> <ScalarProperty Name="FinishedGoodsFlag" ColumnName="FinishedGoodsFlag" /> <ScalarProperty Name="ProductNumber" ColumnName="ProductNumber" /> <ScalarProperty Name="Name" ColumnName="Name" /> <ScalarProperty Name="ProductID" ColumnName="ProductID" /> <ScalarProperty Name="DiscontinuedDate" ColumnName="DiscontinuedDate" /> <Condition ColumnName="MakeFlag" Value="1" /> </MappingFragment> </EntityTypeMapping> </EntitySetMapping> </EntityContainerMapping> </Mapping>
Voir aussi
Tâches
Procédure : définir un modèle avec l'héritage TPT (table par type) (Entity Framework)
Autres ressources
Définition de modèles de données avancés (Tâches Entity Framework)
Spécifications CSDL, SSDL et MSL