Procedura: definire un modello con ereditarietà tabella per gerarchia (Entity Framework)
In questo argomento viene descritto come creare manualmente un modello concettuale con ereditarietà tabella per gerarchia. L'ereditarietà tabella per gerarchia utilizza una tabella di database per gestire i dati relativi a tutti i tipi di entità in una gerarchia di ereditarietà.
Nota: |
---|
Per definire un modello con ereditarietà tabella per tipo è consigliabile utilizzare gli oggetti ADO.NET Entity Data Model Tools.Per ulteriori informazioni, vedere Walkthrough: Mapping Inheritance - Table-per-Hierarchy. |
I passaggi di base per la definizione manuale di un modello con ereditarietà tabella per gerarchia sono i seguenti:
Definire un set di entità nel modello concettuale che conterrà il tipo di entità di base e i tipi derivati. Per ulteriori informazioni, vedere Elemento EntitySet (CSDL).
Definire tipi di entità derivati nel modello concettuale tramite l'attributo BaseType e definire solo proprietà non ereditate per i tipi derivati. Per ulteriori informazioni, vedere Elemento EntityType (CSDL).
Scegliere una colonna della tabella di database sottostante il cui valore verrà utilizzato per discriminare tra il tipo di base e i tipi derivati. Se, ad esempio, una tabella Employee include una colonna EmployeeType con valore Integer, il valore di questa colonna può essere utilizzato per stabilire quando un tipo di entità di base Employee è uno dei tipi di entità derivate seguenti: HourlyEmployee o SalariedEmployee. Per ulteriori informazioni, vedere l'esempio che segue.
La colonna discriminatore viene mappata come parte di una condizione e pertanto non può esistere alcuna proprietà corrispondente per un tipo di entità della gerarchia. L'eccezione a questa regola è quando la condizione utilizza un confronto Is Null o Is Not Null. In questo caso, la colonna discriminatore può contenere una proprietà corrispondente per un tipo di entità.
Se la colonna discriminatore può contenere più di due valori, ad esempio un tipo Integer, deve essere nullable o deve presentare un valore predefinito. In questo modo si garantisce che la colonna possa essere null o presentare un valore quando si crea e si salva nel database un nuovo tipo.
Le condizioni devono essere utilizzate per eseguire il mapping di ogni tipo derivato nella gerarchia, nonché per eseguire il mapping del tipo di base. Se il tipo di base è astratto, non sono consentiti mapping né condizioni.
Eseguire il mapping del tipo di entità di base e dei tipi derivati nello stesso elemento EntitySetMapping in MSL (Mapping Specification Language). Se possibile, eseguire il mapping delle proprietà ereditate alle colonne della tabella. Utilizzare la sintassi
IsTypeOf
quando si imposta il valore dell'attributo TypeName nei tipi derivati. Utilizzare una condizione di mapping per discriminare tra i tipi nella gerarchia. Per ulteriori informazioni, vedere Elemento EntitySetMapping (MSL) e Elemento Condition (MSL).
Nell'esempio seguente si suppone che sia stato installato il database di esempio School e che il progetto sia stato configurato manualmente per l'utilizzo di Entity Framework . Per ulteriori informazioni, vedere Creazione del database di esempio School (Guida rapida di Entity Framework) e Configurazione di Entity Framework (attività di Entity Framework).
Per creare il modello di archiviazione
Aggiungere il file XML seguente al progetto e denominarlo
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>
Per creare il modello concettuale
Aggiungere il file XML seguente al progetto e denominarlo
AdventureWorks.csdl
. Tenere presente quanto segue:Viene definito un solo set di entità, Products, per i due tipi di entità Product e DiscontinuedProduct.
Il tipo di entità DiscontinuedProduct è un tipo derivato come indicato dall'attributo
BaseType
nella definizione.Le proprietà definite nel tipo di entità DiscontinuedProduct sono solo proprietà non ereditate.
La colonna MakeFlag nel modello di archiviazione (vedere il file
AdventureWorks.ssdl
precedente) non viene visualizzata come proprietà nel tipo di base o nel tipo derivato. Il valore di questa colonna verrà utilizzato per discriminare tra i tipi nella gerarchia in quanto viene mappata come parte di una condizione (vedere il fileAdventureWorks.msl
di seguito).
Nota: Se la colonna viene utilizzata in una condizione Is Null o Is Not Null, la proprietà corrispondente può essere visualizzata in un tipo di 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>
Per definire il mapping tra il modello concettuale e il modello di archiviazione
Aggiungere il file XML seguente al progetto e denominarlo
AdventureWorks.msl
. Tenere presente quanto segue:Il mapping per i tipi di entità Product e DiscontinuedProduct è definito nello stesso elemento EntitySetMapping.
Le proprietà ereditate per DiscontinuedProduct vengono mappate alle colonne corrispondenti nella tabella di database sottostante.
La sintassi
IsTypeOf
viene utilizzata per indicare il tipo del tipo derivato DiscontinuedProduct.La colonna discriminatore, MakeFlag, viene mappata in un elemento Condition per ogni tipo di entità nella gerarchia.
<?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>
Vedere anche
Attività
Procedura: definire un modello con ereditarietà tabella per tipo (Entity Framework)
Altre risorse
Definizione di modelli di dati avanzati (attività di Entity Framework)
Specifiche CSDL, SSDL e MSL