Entity Framework: модель во-первых, наследование? - PullRequest
6 голосов
/ 23 декабря 2010

У меня есть таблица Person, таблица Employee и таблица Contractor. Все сотрудники - это люди, все подрядчики - это люди, и каждый человек является либо сотрудником, либо подрядчиком. Вот так: alt text

Как бы я смог реализовать эту концепцию с помощью Model First? Наследование

Ответы [ 2 ]

8 голосов
/ 23 декабря 2010

У вас есть три варианта:

1 - Таблица по иерархии : Хорошо для производительности, так как требуется одна физическая таблица. Вам нужно будет добавить поле дискриминатор к Person - например, "PersonType". Проблема с этим подходом (что я обнаружил) в том, что у вас в конечном итоге будет много пустых полей, а навигационные свойства между производными типами сложны (по моему опыту).

2 - Таблица по типу : Требует отдельных таблиц, но хорош для гибкости, если вы хотите другой другой тип "Person".

3 - Тип таблицы на бетон : с этим не сталкивался, поэтому не могу комментировать. AFAIK это очень похоже на TPT.

Я бы, наверное, пошел с TPT, просто потому что это проще IMO.

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

Шаги для первой модели:

  1. Добавьте эти три объекта в пустой EDMX.
  2. Пометить "Персона" как абстрактную
  3. Установите «Подрядчик» и «Сотрудник» как производные от «Персона». (Добавить -> Наследование)
  4. Удалите поля идентификаторов из сущностей «Сотрудник» и «Подрядчик» (не требуется - он унаследует идентификатор от «Персона»).
  5. Создание базы данных из модели.
3 голосов
/ 23 декабря 2010

Та структура таблицы + наследование == TPT. В конструкторе это будет выглядеть примерно так:

Entity model designer

... и необработанный EDMX для сущностей и сопоставлений с этими таблицами:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns:ssdl="http://schemas.microsoft.com/ado/2009/02/edm/ssdl" xmlns:edm="http://schemas.microsoft.com/ado/2008/09/edm" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns:map="http://schemas.microsoft.com/ado/2008/09/mapping/cs" xmlns:codegen="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:huagati="http://www.huagati.com/edmxtools/annotations">
  <!--Updated by Huagati EDMX Tools version 2.16.4007.30259 on 2010-12-23 09:13:27-->
  <!-- EF Runtime content -->
  <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl" Namespace="Model1.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008">
        <EntityContainer Name="Model1TargetContainer">
          <EntitySet Name="Person" store:Type="Tables" Schema="dbo" Table="Person" store:Name="Person" EntityType="Model1.Store.Person" />
          <EntitySet Name="Employee" store:Type="Tables" Schema="dbo" Table="Employee" store:Name="Employee" EntityType="Model1.Store.Employee" />
          <AssociationSet Name="FK_Employee_Person" Association="Model1.Store.FK_Employee_Person">
            <End Role="Person" EntitySet="Person" />
            <End Role="Employee" EntitySet="Employee" />
          </AssociationSet>
          <EntitySet Name="Contractor" store:Type="Tables" Schema="dbo" Table="Contractor" store:Name="Contractor" EntityType="Model1.Store.Contractor" />
          <AssociationSet Name="FK_Contractor_Person" Association="Model1.Store.FK_Contractor_Person">
            <End Role="Person" EntitySet="Person" />
            <End Role="Contractor" EntitySet="Contractor" />
          </AssociationSet>
        </EntityContainer>
        <EntityType Name="Person">
          <Documentation />
          <Key>
            <PropertyRef Name="PersonId" />
          </Key>
          <Property Name="PersonId" Type="bigint" Nullable="false" StoreGeneratedPattern="Identity" />
          <Property Name="Name" Type="nvarchar" Nullable="true" MaxLength="50" />
        </EntityType>
        <EntityType Name="Employee">
          <Documentation />
          <Key>
            <PropertyRef Name="EmployeeId" />
          </Key>
          <Property Name="EmployeeId" Type="bigint" Nullable="false" />
          <Property Name="EmployeeNumber" Type="nvarchar" Nullable="true" MaxLength="50" />
        </EntityType>
        <Association Name="FK_Employee_Person">
          <End Multiplicity="1" Role="Person" Type="Model1.Store.Person" />
          <End Multiplicity="0..1" Role="Employee" Type="Model1.Store.Employee" />
          <ReferentialConstraint>
            <Principal Role="Person">
              <PropertyRef Name="PersonId" />
            </Principal>
            <Dependent Role="Employee">
              <PropertyRef Name="EmployeeId" />
            </Dependent>
          </ReferentialConstraint>
        </Association>
        <EntityType Name="Contractor">
          <Documentation />
          <Key>
            <PropertyRef Name="ContractorId" />
          </Key>
          <Property Name="ContractorId" Type="bigint" Nullable="false" />
          <Property Name="ContractorNumber" Type="nvarchar" Nullable="true" MaxLength="50" />
        </EntityType>
        <Association Name="FK_Contractor_Person">
          <End Multiplicity="1" Role="Person" Type="Model1.Store.Person" />
          <End Multiplicity="0..1" Role="Contractor" Type="Model1.Store.Contractor" />
          <ReferentialConstraint>
            <Principal Role="Person">
              <PropertyRef Name="PersonId" />
            </Principal>
            <Dependent Role="Contractor">
              <PropertyRef Name="ContractorId" />
            </Dependent>
          </ReferentialConstraint>
        </Association>
      </Schema>
    </edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="Model1" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
        <EntityContainer Name="Model1Container" annotation:LazyLoadingEnabled="true">
          <EntitySet Name="Person" EntityType="Model1.Person" huagati:InheritanceStrategy="TPT" />
        </EntityContainer>
        <EntityType Name="Person">
          <Key>
            <PropertyRef Name="PersonId" />
          </Key>
          <Property Type="Int64" Name="PersonId" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
          <Property Type="String" Name="Name" Unicode="true" MaxLength="50" Nullable="true" />
        </EntityType>
        <EntityType Name="Employee" BaseType="Model1.Person">
          <Property Type="String" Name="EmployeeNumber" Unicode="true" MaxLength="50" Nullable="true" />
        </EntityType>
        <EntityType Name="Contractor" BaseType="Model1.Person">
          <Property Type="String" Name="ContractorNumber" Nullable="true" Unicode="true" MaxLength="50" />
        </EntityType>
      </Schema>
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
      <Mapping xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs" Space="C-S">
        <Alias Key="Model" Value="Model1" />
        <Alias Key="Target" Value="Model1.Store" />
        <EntityContainerMapping CdmEntityContainer="Model1Container" StorageEntityContainer="Model1TargetContainer">
          <EntitySetMapping Name="Person">
            <EntityTypeMapping TypeName="IsTypeOf(Model1.Person)">
              <MappingFragment StoreEntitySet="Person">
                <ScalarProperty Name="PersonId" ColumnName="PersonId" />
                <ScalarProperty Name="Name" ColumnName="Name" />
              </MappingFragment>
            </EntityTypeMapping>
            <EntityTypeMapping TypeName="IsTypeOf(Model1.Employee)">
              <MappingFragment StoreEntitySet="Employee">
                <ScalarProperty Name="PersonId" ColumnName="EmployeeId" />
                <ScalarProperty Name="EmployeeNumber" ColumnName="EmployeeNumber" />
              </MappingFragment>
            </EntityTypeMapping>
            <EntityTypeMapping TypeName="IsTypeOf(Model1.Contractor)">
              <MappingFragment StoreEntitySet="Contractor">
                <ScalarProperty Name="PersonId" ColumnName="ContractorId" />
                <ScalarProperty Name="ContractorNumber" ColumnName="ContractorNumber" />
              </MappingFragment>
            </EntityTypeMapping>
          </EntitySetMapping>
        </EntityContainerMapping>
      </Mapping>
    </edmx:Mappings>
  </edmx:Runtime>
  <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
  <edmx:Designer xmlns="http://schemas.microsoft.com/ado/2008/10/edmx">
    <edmx:Connection>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
      </DesignerInfoPropertySet>
    </edmx:Connection>
    <edmx:Options>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="ValidateOnBuild" Value="true" />
        <DesignerProperty Name="EnablePluralization" Value="True" />
      </DesignerInfoPropertySet>
    </edmx:Options>
    <!-- Diagram content (shape and connector positions) -->
    <edmx:Diagrams>
      <Diagram Name="Model1">
        <EntityTypeShape EntityType="Model1.Person" Width="1.5" PointX="5.125" PointY="2.125" Height="1.4033821614583331" />
        <EntityTypeShape EntityType="Model1.Employee" Width="1.5" PointX="3.875" PointY="4" Height="1.2110807291666665" />
        <InheritanceConnector EntityType="Model1.Employee">
          <ConnectorPoint PointX="5.875" PointY="3.5283821614583331" />
          <ConnectorPoint PointX="5.875" PointY="3.76" />
          <ConnectorPoint PointX="4.625" PointY="3.76" />
          <ConnectorPoint PointX="4.625" PointY="4" />
        </InheritanceConnector>
        <EntityTypeShape EntityType="Model1.Contractor" Width="2" PointX="5.875" PointY="4" Height="1.2110807291666665" />
        <InheritanceConnector EntityType="Model1.Contractor" ManuallyRouted="false">
          <ConnectorPoint PointX="5.875" PointY="3.5283821614583331" />
          <ConnectorPoint PointX="5.875" PointY="3.76" />
          <ConnectorPoint PointX="6.875" PointY="3.76" />
          <ConnectorPoint PointX="6.875" PointY="4" />
        </InheritanceConnector>
      </Diagram>
    </edmx:Diagrams>
  </edmx:Designer>
</edmx:Edmx>

Более подробное описание различных типов наследования и их взаимосвязи с физическими таблицами БД см. В
http://huagati.blogspot.com/2010/10/mixing-inheritance-strategies-in-entity.html
... и ...
http://blogs.msdn.com/b/adonet/archive/2010/10/25/inheritance-mapping-a-walkthrough-guide-for-beginners.aspx

...