Cómo definir un modelo con herencia de tabla por jerarquía (Entity Framework)
En este tema se describe cómo crear de forma manual un modelo conceptual con herencia de tabla por jerarquía. La herencia de tabla por jerarquía usa una tabla de base de datos para mantener los datos de todos los tipos de entidad en una jerarquía de la herencia.
Nota: |
---|
El método recomendado para definir un modelo con una herencia de tabla por tipo es utilizar ADO.NET Entity Data Model Tools.Para obtener más información, vea Walkthrough: Mapping Inheritance - Table-per-Hierarchy. |
Los pasos básicos para definir manualmente un modelo con una herencia de tabla por jerarquía son los siguientes:
Defina un conjunto de entidades en el modelo conceptual que contendrá el tipo de entidad base y los tipos derivados. Para obtener más información, vea EntitySet (Elemento) (CSDL).
Defina los tipos de entidad derivada en el modelo conceptual mediante el atributo BaseType y defina solo propiedades no heredadas en los tipos derivados. Para obtener más información, vea EntityType (Elemento) (CSDL).
Elija una columna de la tabla de base de datos subyacente cuyo valor se utilizará para diferenciar entre los tipos base y los tipos derivados. Por ejemplo, si una tabla Employee tiene una columna EmployeeType con valores enteros, el valor de esta columna se puede utilizar para distinguir cuando un tipo de entidad base Employee es uno de los siguientes tipos de entidad derivados: HourlyEmployee o SalariedEmployee. Para obtener más información, vea el siguiente ejemplo.
La columna de discriminadora se asigna como parte de una condición, por lo que no puede haber ninguna propiedad correspondiente en ningún tipo de entidad de la jerarquía. La excepción a esta regla se produce cuando la condición utiliza una comparación Is Null o Is Not Null. En este caso, la columna discriminadora puede tener una propiedad correspondiente en un tipo de entidad.
Si la columna discriminadora puede tener más de dos valores (un tipo entero, por ejemplo), la columna debe aceptar valores NULL o tener una valor predeterminado. De esta forma se garantiza que al crear y guardar un nuevo tipo en la base de datos, la columna puede ser NULL o tener alguna valor.
Se deben usar condiciones para asignar cada tipo derivado de la jerarquía y se pueden usar también para asignar el tipo base. Si el tipo base es abstracto, no se permite ninguna asignación ni condición.
Asigne el tipo de entidad base y los tipos derivados del mismo elemento EntitySetMapping en el lenguaje de especificación de asignaciones (MSL). Asigne propiedades heredadas a columnas de tabla cuando resulte adecuado. Utilice la sintaxis
IsTypeOf
al establecer el valor del atributo TypeName en tipos derivados. Utilice una condición de asignación para diferenciar entre los tipos de la jerarquía. Para obtener más información, vea EntitySetMapping (Elemento) (MSL) y Condition (Elemento) (MSL).
El siguiente ejemplo supone que ha instalado la base de datos de ejemplo School y que ha configurado manualmente el proyecto para que utilice Entity Framework . Para obtener más información, vea Crear la aplicación de ejemplo School (Tutorial rápido de Entity Framework) y Configurar Entity Framework (tareas de Entity Framework).
Para crear el modelo de almacenamiento
Agregue el siguiente archivo XML a su proyecto y denomínelo
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>
Para crear el modelo conceptual
Agregue el siguiente archivo XML a su proyecto y denomínelo
AdventureWorks.csdl
. Tenga en cuenta los siguientes extremos:Solo se define un conjunto de entidades, Products, para los dos tipos de entidad: Product y DiscontinuedProduct.
El tipo de entidad DiscontinuedProduct es un tipo derivado, tal como indica el atributo
BaseType
en su definición.Las propiedades definidas en el tipo de entidad DiscontinuedProduct son únicamente propiedades no heredadas.
La columna MakeFlag del modelo de almacenamiento (vea el archivo
AdventureWorks.ssdl
anterior) no aparece como una propiedad en el tipo base ni el tipo derivado. El valor de esta columna se utilizará para diferenciar entre los tipos de la jerarquía a medida que se asigna como parte de una condición (vea el archivoAdventureWorks.msl
siguiente).
Nota: Si la columna se utiliza en una condición Is Null o Is Not Null, la propiedad correspondiente puede aparecer en un tipo de entidad.
<?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>
Para definir la asignación entre el modelo conceptual y el modelo de almacenamiento
Agregue el siguiente archivo XML a su proyecto y denomínelo
AdventureWorks.msl
. Tenga en cuenta los siguientes extremos:La asignación de los tipos de entidad Product y DiscontinuedProduct se define en el mismo elemento EntitySetMapping.
Las propiedades heredadas de DiscontinuedProduct se asignan a las columnas correspondientes en la tabla de base de datos subyacente.
La sintaxis
IsTypeOf
se utiliza para indicar el tipo del tipo DiscontinuedProduct derivado.La columna discriminadora, MakeFlag, se asigna en un elemento Condition para cada tipo de entidad de la jerarquía.
<?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>
Vea también
Tareas
Cómo: Definir un modelo con herencia de tabla por tipo (Entity Framework)
Otros recursos
Definir modelos de datos avanzados (tareas de Entity Framework)
Especificaciones CSDL, SSDL y MSL