如何:通过每种类型一个表继承以定义模型(实体框架)
在 实体数据模型 (EDM) 中可以通过多种方式实现继承。每种类型一个表 (table-per-type) 方法针对继承层次结构中的每种类型,在存储中使用一个单独的表为其维护数据。本节包含用于在每种类型一个表方案中实现的简单继承层次结构的架构和映射。
在 (EDM) 中,每种类型一个表模型中继承层次结构的概念架构在派生类型的声明中包含 BaseType 属性指定。每个派生的 EntityType 单独声明,但 EntityContainer 的声明仅包含基类型的 EntitySet 声明。
本方案中的关联在基类型之上实现,因为关联的定义指的是 EntitySet 声明。派生类型在 EntityContainer 中没有 EntitySet 声明。
为每种类型一个表继承实现概念架构
创建类库项目。
单击**“添加新项”**,添加一个 ADO.NET 实体数据模型。
当向导出现时,创建一个空模型。
使用 XML 编辑器打开 .edmx 文件,添加该文件的概念架构定义语言 (CSDL) 段。
实现 CSDL 架构。此架构包括名为 SchoolDataLib 的命名空间中的声明。此继承层次结构包含名为 Department 的 EntityType,这是一个基类型,并且三个派生实体分别对应于工商系、工程系和音乐系。仅有基类型 Department 具有 Key 属性指定。派生类型 DeptBusiness、DeptEngineering 和 DeptMusic 包含 BaseType 属性指定。在存储中表示派生类型的各表中的 Key 列全部映射到表示基类型的表中的 Key 列。
在 Department 实体与 Person 实体之间实现 AssociationType。此关联用于为 SchoolAdministrator 实现导航属性。FK_Department_Administrator 定义一个关联,此关联由从 Department 类型(在其中声明关联)派生的所有类型使用。所有派生类型都继承使用此 AssociationType 的 NavigationProperty。以下显示完整的 CSDL 架构。
<!-- CSDL content -->
<Schema
xmlns="https://schemas.microsoft.com/ado/2006/04/edm"
Namespace="SchoolDataLib"
Alias="Self">
<EntityType Name="Department">
<!--Base type table-per-type inheritance-->
<Key>
<PropertyRef Name="DepartmentID" />
</Key>
<Property Name="DepartmentID" Type="Int32" Nullable="false" />
<Property Name="Name" Type="String" Nullable="false" />
<Property Name="Budget" Type="Decimal" Nullable="false" />
<Property Name="StartDate" Type="DateTime" Nullable="false" />
<NavigationProperty Name="Administrator"
Relationship="SchoolDataLib.FK_Department_Administrator"
FromRole="Department" ToRole="Person" />
</EntityType>
<EntityType Name="DeptBusiness" BaseType="SchoolDataLib.Department">
<Property Name="LegalBudget" Type="Decimal" Nullable="false" />
<Property Name="AccountingBudget" Type="Decimal" Nullable="false" />
</EntityType>
<EntityType Name="DeptEngineering" BaseType="SchoolDataLib.Department">
<Property Name="FiberOpticsBudget" Type="Decimal" Nullable="false" />
<Property Name="LabBudget" Type="Decimal" Nullable="false" />
</EntityType>
<EntityType Name="DeptMusic" BaseType="SchoolDataLib.Department">
<Property Name="TheaterBudget" Type="Decimal" Nullable="false" />
<Property Name="InstrumentBudget" Type="Decimal" Nullable="false" />
</EntityType>
<Association Name="FK_Department_Administrator">
<End Role="Person" Type="SchoolDataLib.Person" Multiplicity="0..1" />
<End Role="Department" Type="SchoolDataLib.Department" Multiplicity="*" />
</Association>
<EntityType Name="Person">
<!--Base type table-per-hierarchy inheritance-->
<Key>
<PropertyRef Name="PersonID" />
</Key>
<Property Name="PersonID" Type="Int32" Nullable="false" />
<Property Name="FirstName" Type="String" Nullable="false" />
<Property Name="LastName" Type="String" Nullable="false" />
<NavigationProperty Name="Department"
Relationship="SchoolDataLib.FK_Department_Administrator"
FromRole="Person" ToRole="Department" />
</EntityType>
<EntityType Name="Student" BaseType="SchoolDataLib.Person">
<Property Name="EnrollmentDate" Type="DateTime" />
</EntityType>
<EntityType Name="Instructor" BaseType="SchoolDataLib.Person">
<Property Name="HireDate" Type="DateTime" />
</EntityType>
<EntityType Name="Administrator" BaseType="SchoolDataLib.Person">
<Property Name="AdminDate" Type="DateTime" />
</EntityType>
<EntityContainer Name="SchoolDataLibContainer">
<EntitySet Name="Departments" EntityType="SchoolDataLib.Department" />
<EntitySet Name="People" EntityType="SchoolDataLib.Person" />
<AssociationSet Name="FK_Department_Administrator"
Association="SchoolDataLib.FK_Department_Administrator">
<End Role="Person" EntitySet="People" />
<End Role="Department" EntitySet="Departments" />
</AssociationSet>
</EntityContainer>
</Schema>
为每种类型一个表继承实现存储架构
定义一些表,这些表包含 .edmx 文件的存储架构定义语言 (SSDL) 段中继承层次结构中的每个类型的数据。与概念架构中的实体声明不同,存储模型中的派生类型的实体具有一个 Key 属性。
对于存储架构中的属性,使用数据库管理系统的数据类型,而非在概念架构中使用的公共语言运行库 (CLR) 类型。
在 SSDL 中使用下面的语法定义此继承方案中使用的完整存储元数据。
<!-- SSDL content -->
<Schema
xmlns="https://schemas.microsoft.com/ado/2006/04/edm/ssdl"
Namespace="SchoolDataLib.Target"
Provider="System.Data.SqlClient"
ProviderManifestToken="2005"
Alias="Self">
<EntityContainer Name="dbo">
<EntitySet Name="Department" EntityType="SchoolDataLib.Target.Department" />
<EntitySet Name="DeptBusiness" EntityType="SchoolDataLib.Target.DeptBusiness" />
<EntitySet Name="DeptEngineering" EntityType="SchoolDataLib.Target.DeptEngineering" />
<EntitySet Name="DeptMusic" EntityType="SchoolDataLib.Target.DeptMusic" />
<EntitySet Name="Person" EntityType="SchoolDataLib.Target.Person" />
<AssociationSet Name="FK_Department_Administrator"
Association="SchoolDataLib.Target.FK_Department_Administrator">
<End Role="Person" EntitySet="Person" />
<End Role="Department" EntitySet="Department" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Department">
<Key>
<PropertyRef Name="DepartmentID" />
</Key>
<Property Name="DepartmentID" Type="int" Nullable="false" />
<Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Budget" Type="money" Nullable="false" />
<Property Name="StartDate" Type="datetime" Nullable="false" />
<Property Name="Administrator" Type="int" />
</EntityType>
<EntityType Name="DeptBusiness">
<Key>
<PropertyRef Name="BusinessDeptID" />
</Key>
<Property Name="BusinessDeptID" Type="int" Nullable="false" />
<Property Name="LegalBudget" Type="money" Nullable="false" />
<Property Name="AccountingBudget" Type="money" Nullable="false" />
</EntityType>
<EntityType Name="DeptEngineering">
<Key>
<PropertyRef Name="EngineeringDeptID" />
</Key>
<Property Name="EngineeringDeptID" Type="int" Nullable="false" />
<Property Name="FiberOpticsBudget" Type="money" Nullable="false" />
<Property Name="LabBudget" Type="money" Nullable="false" />
</EntityType>
<EntityType Name="DeptMusic">
<Key>
<PropertyRef Name="DeptMusicID" />
</Key>
<Property Name="DeptMusicID" Type="int" Nullable="false" />
<Property Name="TheaterBudget" Type="money" Nullable="false" />
<Property Name="InstrumentBudget" Type="money" Nullable="false" />
</EntityType>
<EntityType Name="Person">
<Key>
<PropertyRef Name="PersonID" />
</Key>
<Property Name="PersonID" Type="int" Nullable="false" />
<Property Name="FirstName" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="LastName" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="HireDate" Type="datetime" />
<Property Name="EnrollmentDate" Type="datetime" />
<Property Name="AdminDate" Type="datetime" />
<Property Name="PersonCategory" Type="smallint" Nullable="false" />
</EntityType>
<Association Name="FK_Department_Administrator">
<End Role="Person" Type="SchoolDataLib.Target.Person" Multiplicity="0..1" />
<End Role="Department" Type="SchoolDataLib.Target.Department" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Person">
<PropertyRef Name="PersonID" />
</Principal>
<Dependent Role="Department">
<PropertyRef Name="Administrator" />
</Dependent>
</ReferentialConstraint>
</Association>
</Schema>
使用 SQL Server Management Studio 生成数据库
在 SQL Server Management Studio 中使用以下脚本以生成在本示例和示例如何:通过每个层次结构一个表继承以定义模型(实体框架) 中使用的数据库。
在“文件”菜单上,指向**“新建”,然后单击“数据库引擎查询”**。
在**“连接到数据库引擎”对话框中键入 localhost 或其他 SQL Server 实例的名称,然后单击“连接”**。
将以下 Transact-SQL 脚本粘贴到查询窗口中,然后单击“执行”。
USE [master]
GO
CREATE DATABASE [SchoolData]
GO
USE [SchoolData]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DeptBusiness]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[DeptBusiness](
[BusinessDeptID] [int] NOT NULL,
[LegalBudget] [money] NOT NULL,
[AccountingBudget] [money] NOT NULL,
CONSTRAINT [PK_DeptBusiness] PRIMARY KEY CLUSTERED
(
[BusinessDeptID] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DeptEngineering]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[DeptEngineering](
[EngineeringDeptID] [int] NOT NULL,
[FiberOpticsBudget] [money] NOT NULL,
[LabBudget] [money] NOT NULL,
CONSTRAINT [PK_DeptEngineering] PRIMARY KEY CLUSTERED
(
[EngineeringDeptID] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DeptMusic]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[DeptMusic](
[DeptMusicID] [int] NOT NULL,
[TheaterBudget] [money] NOT NULL,
[InstrumentBudget] [money] NOT NULL,
CONSTRAINT [PK_DeptMusic] PRIMARY KEY CLUSTERED
(
[DeptMusicID] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Course]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Course](
[CourseID] [int] NOT NULL,
[Title] [nvarchar](100) NOT NULL,
[StartDate] [datetime] NOT NULL,
[EndDate] [datetime] NOT NULL,
[Credits] [int] NULL,
CONSTRAINT [PK_Course] PRIMARY KEY CLUSTERED
(
[CourseID] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Person]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Person](
[PersonID] [int] NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[HireDate] [datetime] NULL,
[EnrollmentDate] [datetime] NULL,
[PersonCategory] [smallint] NOT NULL,
[AdminDate] [datetime] NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
[PersonID] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Enrollment]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Enrollment](
[EnrollmentID] [int] NOT NULL,
[CourseID] [int] NOT NULL,
[StudentID] [int] NOT NULL,
CONSTRAINT [PK_Enrollment] PRIMARY KEY CLUSTERED
(
[EnrollmentID] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[CourseInstructor]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[CourseInstructor](
[CourseInstructorID] [int] NOT NULL,
[CourseID] [int] NOT NULL,
[InstructorID] [int] NOT NULL,
CONSTRAINT [PK_CourseInstructor] PRIMARY KEY CLUSTERED
(
[CourseInstructorID] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Department]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Department](
[DepartmentID] [int] NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[Budget] [money] NOT NULL,
[StartDate] [datetime] NOT NULL,
[Administrator] [int] NULL,
CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED
(
[DepartmentID] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Enrollment_Course]') AND parent_object_id = OBJECT_ID(N'[dbo].[Enrollment]'))
ALTER TABLE [dbo].[Enrollment] WITH CHECK ADD CONSTRAINT [FK_Enrollment_Course] FOREIGN KEY([CourseID])
REFERENCES [dbo].[Course] ([CourseID])
GO
ALTER TABLE [dbo].[Enrollment] CHECK CONSTRAINT [FK_Enrollment_Course]
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Enrollment_Student]') AND parent_object_id = OBJECT_ID(N'[dbo].[Enrollment]'))
ALTER TABLE [dbo].[Enrollment] WITH CHECK ADD CONSTRAINT [FK_Enrollment_Student] FOREIGN KEY([StudentID])
REFERENCES [dbo].[Person] ([PersonID])
GO
ALTER TABLE [dbo].[Enrollment] CHECK CONSTRAINT [FK_Enrollment_Student]
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_CourseInstructor_Course]') AND parent_object_id = OBJECT_ID(N'[dbo].[CourseInstructor]'))
ALTER TABLE [dbo].[CourseInstructor] WITH CHECK ADD CONSTRAINT [FK_CourseInstructor_Course] FOREIGN KEY([CourseID])
REFERENCES [dbo].[Course] ([CourseID])
GO
ALTER TABLE [dbo].[CourseInstructor] CHECK CONSTRAINT [FK_CourseInstructor_Course]
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_CourseInstructor_Instructor]') AND parent_object_id = OBJECT_ID(N'[dbo].[CourseInstructor]'))
ALTER TABLE [dbo].[CourseInstructor] WITH CHECK ADD CONSTRAINT [FK_CourseInstructor_Instructor] FOREIGN KEY([InstructorID])
REFERENCES [dbo].[Person] ([PersonID])
GO
ALTER TABLE [dbo].[CourseInstructor] CHECK CONSTRAINT [FK_CourseInstructor_Instructor]
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Department_Administrator]') AND parent_object_id = OBJECT_ID(N'[dbo].[Department]'))
ALTER TABLE [dbo].[Department] WITH CHECK ADD CONSTRAINT [FK_Department_Administrator] FOREIGN KEY([Administrator])
REFERENCES [dbo].[Person] ([PersonID])
GO
ALTER TABLE [dbo].[Department] CHECK CONSTRAINT [FK_Department_Administrator]
为每种类型一个表继承实现映射规范
在用于基类型的 EntitySet 映射之下,对于派生类型组合 EntityTypeMapping 标记。在以下映射规范语言 (MSL) 架构中,根据概念架构中的定义,将 EntitySet 命名为 Departments。
在 EntitySet 映射之下,将 EntityTypeMapping 标记同时用于基类型和派生类型。
通过 TypeName 属性,指定要在 EntityTypeMapping 之下映射的每种类型。
在 TableName 属性之后附加 TableMappingFragment。
通过使用 ScalarProperty 标记,将实体类型的属性映射到在存储元数据中指定的列。
请注意,派生类型的标识列全部映射到基类型的标识属性(在此情况下,此属性的名称为 DepartmentID)。
使用以下 MSL 语法,通过使用基类 Department 映射 EntitySet。
为每个派生类型指定一个 EntityTypeMapping。
<!-- C-S mapping content -->
<Mapping xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS"
Space="C-S">
<Alias Key="Model" Value="SchoolDataLib" />
<Alias Key="Target" Value="SchoolDataLib.Target" />
<EntityContainerMapping CdmEntityContainer="SchoolDataLibContainer"
StorageEntityContainer="dbo">
<!-- Mapping for table-per-type inheritance-->
<EntitySetMapping Name="Departments">
<EntityTypeMapping
TypeName="IsTypeOf(SchoolDataLib.Department)">
<MappingFragment StoreEntitySet="Department">
<ScalarProperty
Name="DepartmentID" ColumnName="DepartmentID" />
<ScalarProperty Name="Name" ColumnName="Name" />
<ScalarProperty Name="Budget" ColumnName="Budget" />
<ScalarProperty
Name="StartDate" ColumnName="StartDate" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="SchoolDataLib.DeptBusiness">
<MappingFragment StoreEntitySet="DeptBusiness">
<ScalarProperty Name="DepartmentID"
ColumnName="BusinessDeptID" />
<ScalarProperty Name="AccountingBudget"
ColumnName="AccountingBudget" />
<ScalarProperty Name="LegalBudget"
ColumnName="LegalBudget" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="SchoolDataLib.DeptEngineering">
<MappingFragment StoreEntitySet="DeptEngineering">
<ScalarProperty Name="DepartmentID"
ColumnName="EngineeringDeptID" />
<ScalarProperty Name="FiberOpticsBudget"
ColumnName="FiberOpticsBudget" />
<ScalarProperty Name="LabBudget"
ColumnName="LabBudget" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="SchoolDataLib.DeptMusic">
<MappingFragment StoreEntitySet="DeptMusic">
<ScalarProperty Name="DepartmentID"
ColumnName="DeptMusicID" />
<ScalarProperty Name="TheaterBudget"
ColumnName="TheaterBudget" />
<ScalarProperty Name="InstrumentBudget"
ColumnName="InstrumentBudget" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<!--Mapping for table-per-hierarchy inheritance-->
<EntitySetMapping Name="People">
<EntityTypeMapping TypeName="SchoolDataLib.Person">
<MappingFragment StoreEntitySet="Person">
<ScalarProperty Name="PersonID" ColumnName="PersonID"/>
<ScalarProperty Name="FirstName" ColumnName="FirstName"/>
<ScalarProperty Name="LastName" ColumnName="LastName"/>
<Condition ColumnName="PersonCategory" Value="0" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="SchoolDataLib.Student">
<MappingFragment StoreEntitySet="Person">
<ScalarProperty Name="PersonID" ColumnName="PersonID" />
<ScalarProperty Name="FirstName" ColumnName="FirstName" />
<ScalarProperty Name="LastName" ColumnName="LastName" />
<ScalarProperty
Name="EnrollmentDate" ColumnName="EnrollmentDate" />
<Condition ColumnName="PersonCategory" Value="1" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="SchoolDataLib.Instructor">
<MappingFragment StoreEntitySet="Person">
<ScalarProperty Name="PersonID" ColumnName="PersonID" />
<ScalarProperty Name="FirstName" ColumnName="FirstName" />
<ScalarProperty Name="LastName" ColumnName="LastName" />
<ScalarProperty Name="HireDate" ColumnName="HireDate" />
<Condition ColumnName="PersonCategory" Value="2" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="SchoolDataLib.Administrator">
<MappingFragment StoreEntitySet="Person">
<ScalarProperty Name="PersonID" ColumnName="PersonID" />
<ScalarProperty Name="FirstName" ColumnName="FirstName" />
<ScalarProperty Name="LastName" ColumnName="LastName" />
<ScalarProperty Name="AdminDate" ColumnName="AdminDate" />
<Condition ColumnName="PersonCategory" Value="3" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<AssociationSetMapping Name="FK_Department_Administrator"
TypeName="SchoolDataLib.FK_Department_Administrator"
StoreEntitySet="Department">
<EndProperty Name="Person">
<ScalarProperty Name="PersonID" ColumnName="Administrator" />
</EndProperty>
<EndProperty Name="Department">
<ScalarProperty Name="DepartmentID" ColumnName="DepartmentID" />
</EndProperty>
<Condition ColumnName="Administrator" IsNull="false" />
</AssociationSetMapping>
</EntityContainerMapping>
</Mapping>
另请参见
任务
如何:通过每种类型一个表继承以定义模型(实体框架)
如何:通过每种类型一个表继承添加和修改对象(实体框架)
如何:通过每个层次结构一个表继承以定义模型(实体框架)