Как определить модель с наследованием типа «одна таблица на иерархию» (платформа Entity Framework)

В этом разделе описывается, как вручную создать концептуальную модель с иерархией наследования «одна таблица на иерархию». Наследование типа «одна таблица на иерархию» использует одну таблицу базы данных для сопровождения данных для всех типов сущности в иерархии наследования.

Bb738443.note(ru-ru,VS.100).gifПримечание
Рекомендуется определять модель с наследованием «одна таблица на тип» с помощью ADO.NET Entity Data Model Tools.Дополнительные сведения см. в разделе Walkthrough: Mapping Inheritance - Table-per-Hierarchy.

Далее представлены основные действия по определению модели с наследованием «одна таблица на иерархию» вручную.

  1. Определите в концептуальной модели один набор сущностей, который содержит базовый тип сущности и производные типы. Дополнительные сведения см. в разделе Элемент EntitySet (CSDL).

  2. Определите в концептуальной модели производные типы сущностей с помощью атрибута BaseType и определите в производных типах только ненаследуемые свойства. Дополнительные сведения см. в разделе Элемент EntityType (язык CSDL).

  3. Выберите из базовой таблицы базы данных столбец, значение которого будет использоваться для различия между основным и производным типами. Например, если в таблице Employee есть столбец EmployeeType с целочисленным значением, то его значение можно использовать для определения того, когда базовый тип сущности Employee является одним из следующих производных типов сущности: HourlyEmployee или SalariedEmployee. Дополнительные сведения см. в следующем примере.

    Столбец дискриминатора сопоставляется в рамках условия, поэтому соответствующего свойства или типов сущности в иерархии быть не может. Исключением к этому правилу является случай, когда в условии имеется сравнение Is Null или Is Not Null. В этом случае у столбца дискриминатора может быть соответствующее свойство или тип сущности.

    Если у столбца дискриминатора может быть более двух значений (например, целочисленных), столбец должен допускать значение null или иметь значение по умолчанию. Тем самым гарантируется, что при создании нового типа и сохранении его в базе данных значение столбца может быть равно null или другому значению.

    Условия следует использовать для сопоставления каждого производного типа в иерархии и можно использовать для сопоставления базового типа. Если базовый тип окажется абстрактным, сопоставления или условия не допускаются.

  4. Сопоставьте базовый тип сущности и производные типы в одном элементе EntitySetMapping на языке MSL. Сопоставьте наследуемые свойства со столбцами таблицы там, где нужно. При задании значения атрибута TypeName производных типов используйте синтаксис IsTypeOf. Для различения типов в иерархии используйте условие сопоставления. Дополнительные сведения см. в разделах Элемент EntitySetMapping (язык MSL) и Элемент Condition (язык MSL).

В следующем примере предполагается, что установлен образец базы данных School, а проект вручную настроен для использования Entity Framework . Дополнительные сведения см. в разделах Создание образца базы данных School (краткое руководство по Entity Framework) и Настройка платформы Entity Framework (задачи Entity Framework).

Создание модели хранения

  1. Добавьте следующий 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>
    

Создание концептуальной модели

  1. Добавьте следующий XML-файл в проект и назовите его AdventureWorks.csdl. Обратите внимание на следующие моменты.

    • Для двух типов сущности Product и DiscontinuedProduct определяется только один набор сущностей Products.

    • Тип сущности DiscontinuedProduct является производным, на что указывает атрибут BaseType в его определении.

    • Для типов сущности DiscontinuedProduct определяются только ненаследуемые свойства.

    • Столбец MakeFlag модели хранения (см. файл AdventureWorks.ssdl выше) не является свойством базового или производного типа. Значение этого столбца будет использоваться для различения типов в иерархии и сопоставляется как часть условия (см. файл AdventureWorks.msl ниже).

    Bb738443.note(ru-ru,VS.100).gifПримечание
    Если столбец используется в условии 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>

Определение сопоставления между концептуальной моделью и моделью хранения

  1. Добавьте следующий XML-файл в проект и назовите его AdventureWorks.msl. Обратите внимание на следующие моменты.

    • Сопоставление для типов сущности Product и DiscontinuedProduct определяется в одном элементе EntitySetMapping.

    • Наследуемые свойства DiscontinuedProduct сопоставляются с соответствующими столбцами в базовых таблицах базы данных.

    • Синтаксис IsTypeOf используется для указания типа производного типа DiscontinuedProduct.

    • Столбец дискриминатора MakeFlag сопоставляется в элементе Condition для каждого типа сущности в иерархии.

    <?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>
    

См. также

Задачи

Как определить модель с наследованием «одна таблица на тип» (платформа Entity Framework)

Другие ресурсы

Определение расширенных моделей данных (задачи платформы Entity Framework)
Спецификации языка CSDL, SSDL и MSL