如何:通过每个层次结构一个表继承以定义模型(实体框架)
本主题介绍如何手动创建具有每个层次结构一个表继承的概念模型。 每个层次结构一个表继承使用一个数据库表来维护继承层次结构中的所有实体类型的数据。
注意: |
---|
建议使用 ADO.NET Entity Data Model Tools来定义具有每种类型一个表继承的模型。有关更多信息,请参见Walkthrough: Mapping Inheritance - Table-per-Hierarchy。 |
以下是手动定义一个具有每个层次结构一个表继承的模型的基本步骤:
在将包含基实体类型和派生类型的概念模型中定义一个实体集。 有关更多信息,请参见 EntitySet 元素 (CSDL)。
通过使用 BaseType 特性在概念模型中定义派生实体类型,并且只定义派生类型上的非继承属性。 有关更多信息,请参见 EntityType 元素 (CSDL)。
从基础数据库表中选择一个列,其值将用于区分基类型和派生类型。 例如,如果 Employee 表具有一个整数值 EmployeeType 列,则此列的值在 Employee 基实体类型为下列派生实体类型之一时用于鉴别:HourlyEmployee 或 SalariedEmployee。 有关更多信息,请参见下面的示例。
由于鉴别器列将作为条件的一部分进行映射,因此层次结构中的任何实体类型上都没有对应的属性。 当条件使用 Is Null 或 Is Not Null 比较时,此规则不适用。 在此情况下,鉴别器列可具有实体类型上的对应属性。
如果鉴别器列可具有多个值(例如,整数类型),则该列必须可为 null 或具有默认值。 这将确保,在创建新类型并将其保存到数据库中时,该列可为 null 或具有某个值。
条件必须用于映射层次结构中的每个派生类型,并且条件可用于映射基类型。 如果基类型是抽象的,则不允许任何映射或条件。
在以映射规范语言 (MSL) 表示的 EntitySetMapping 元素中映射基实体类型和派生类型。 将继承的属性映射到表列(如果适用)。 在设置派生类型的 TypeName 特性的值时使用
IsTypeOf
语法。 使用映射条件区分层次结构中的类型。 有关更多信息,请参见 EntitySetMapping 元素 (MSL) 和 Condition 元素 (MSL)。
下面的示例假定您已经安装了 School 示例数据库,并且您已经手动将项目配置为使用实体框架 。 有关更多信息,请参见创建 School 示例数据库(实体框架快速入门)和配置实体框架(实体框架任务)。
创建存储模型
将下面的 XML 文件添加到您的项目中并将其命名为
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>
创建概念模型
将下面的 XML 文件添加到您的项目中并将其命名为
AdventureWorks.csdl
。 注意下列事项:仅为两个实体类型 Product 和 DiscontinuedProduct 定义一个实体集 Products。
DiscontinuedProduct 实体类型是一个派生类型,此派生类型由其定义中的
BaseType
特性指示。DiscontinuedProduct 实体类型上定义的属性是仅非继承属性。
存储模型中的 MakeFlag 列(请参见上面的
AdventureWorks.ssdl
文件)不会作为基类型或派生类型上的属性出现。 由于此列将作为条件的一部分进行映射,因此其值将用于区分层次结构中的类型(请参见下面的AdventureWorks.msl
文件)。
注意: 如果在 Is Null 或 Is Not Null 条件中使用此列,则对应的属性可在实体类型上出现。
<?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>
定义概念模型与存储模型之间的映射
将下面的 XML 文件添加到您的项目中并将其命名为
AdventureWorks.msl
。 注意下列事项:在同一个 EntitySetMapping 元素中定义 Product 和 DiscontinuedProduct 实体类型的映射。
DiscontinuedProduct 的继承属性将映射到基础数据库表中的对应列。
IsTypeOf
语法用于指示派生的 DiscontinuedProduct 类型的类型。在 Condition 元素中为层次结构中的每个实体类型映射鉴别器列 MakeFlag。
<?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>