Vererbung (EDM)

Mittels Vererbung kann in Entitätsdatenmodell (EDM) ein abgeleiteter Typ die Funktionen eines anderen Typs erweitern.

Üblicherweise umfasst das von einer Anwendung verwendete Modell viele verschiedene Typen. Einige Entitätstypen modellieren separate Begriffe, wie z. B. Kunden und Aufträge****in einer Geschäftsanwendung. Diese Datentypen haben keine gemeinsamen Member. Es gibt jedoch andere Typen, die einander ähnlicher sind. Betrachten Sie beispielsweise die Kunden- und Mitarbeitertypen. Obwohl diese Typen unterschiedliche Konzepte modellieren, gibt es eine grundlegende Gemeinsamkeit: Beide stellen Personen dar, die an Geschäftsbeziehungen beteiligt sind, und beide enthalten Eigenschaften zum Speichern von Informationen, wie Name, Adresse und Telefonnummer.

Bei der EDM-Vererbung kann ein Typ von einem anderen abgeleitet werden. Beispielsweise können sowohl Employee als auch Customer vom Contact-Typ erben. In diesem Fall wird Contact als Basistyp bezeichnet. Employee und Customer werden als abgeleitete Typen bezeichnet.

Eine Vererbung ist nicht zwangsläufig auf eine Ebene beschränkt. Ein abgeleiteter Typ kann auch der Basistyp eines weiteren Entitätstyps sein. Beispielsweise ist Employee ein Basistyp von Manager, Customer ist ein Basistyp von PreferredCustomer usw. Auf diese Weise werden Vererbungshierarchien erzeugt.

Wie die Common Language Runtime (CLR) unterstützt das EDM-System nur die einzelne Vererbung von Datentypen. Ein Entitätstyp kann Eigenschaften nur direkt von einem einzigen übergeordneten Typ erben.

NoteHinweis

Da vom EDM-System keine Methoden implementiert werden, wird die Vererbung von Methoden nicht unterstützt. Im EDM werden Hilfsmethoden in partielle Klassen implementiert. Weitere Informationen finden Sie unter Hilfsmethoden (EDM).

Vererbungsbeispiele

Das folgende Beispiel zeigt eine partielle CSDL-Spezifikation () für die zuvor beschriebene Vererbungshierarchie:

  <EntityType Name="Contact">
    <Key>
      <PropertyRef Name="ContactId" />
    </Key>
    <Property Name="ContactId" Type="Int32" Nullable="false" />
    <Property Name="Name" Type="String" />
    <Property Name="Address" Type="Address" />
    <Property Name="Phone" Type="String" />
  </EntityType>

  <EntityType Name="Customer" BaseType="Contact">
    <Property Name="CustomerID" Type="String" />
    <Property Name="CompanyName" Type="String" />
  </EntityType>

  <EntityType Name="PreferredCustomer" BaseType="Customer">
    <Property Name="PreferenceCode" Type="String" />
    <Property Name="CreditLimit" Type="Decimal" />
  </EntityType>
  <!-- Similar Declarations for Employee and Manager -->

Ein Zweck der Vererbung ist die gemeinsame Verwendung einer grundlegenden Struktur zwischen mehreren Typen. Ein weiterer Grund für Vererbung ist die Erweiterungsfähigkeit. Auch nachdem eine Vererbungshierarchie implementiert und in einer Anwendung bereitgestellt wurde, können Entwickler die Typen mittels Vererbung erweitern.

Das objektorientierte Programmierkonzept von Polymorphie oder Wertersetzbarkeit basiert auf Vererbung. Jede Instanz eines abgeleiteten Datentyps ist auch eine Instanz des zugehörigen Basistyps. Wenn beispielsweise Manager von Employee abgeleitet ist, ist jede Instanz von Manager auch eine Instanz von Employee. Wenn Sie eine Abfrage für alle Mitarbeiter (den Basistyp) ausführen, erhalten Sie auch alle Manager (den abgeleiteten Typ).

Weitere Informationen über Vererbung finden Sie unter Gewusst wie: Definieren eines Modells mit einer 'Tabelle pro Typ'-Vererbung und Gewusst wie: Definieren eines Modells mit 'Tabelle pro Hierarchie'-Vererbung (Entity Framework).

Implementierung der Vererbung

Eine wie in CSDL definierte Vererbungshierarchie muss in die Datenbanktabellen implementiert werden, in denen Daten für eine auf dem EDM-Modell basierende Anwendung gespeichert werden. Es gibt verschiedene Möglichkeiten, wie die Typen in einer Vererbungshierarchie in den Datenbanktabellen strukturiert sein können.

Bei allen Implementierungen muss die Schlüsselstruktur von Basistypen und abgeleiteten Typen identisch sein. Wenn daher ein Customer-Typ vom Person-Typ abgeleitet ist, müssen sowohl der Customer-Typ als auch der Person-Typ dieselben Schlüsseleigenschaften festlegen.

Bei Implementierungen einer Vererbung mit mehreren Tabellen wird der Schlüsseleigenschaft in mehreren Tabellen derselbe Wert zugewiesen, um abgeleitete Typen als Instanzen von übergeordneten Typen zu kennzeichnen.

In der Mappingspezifikation können Implementierungen einer Vererbung den IsTypeOf<T>-Indikator in EntityTypeMapping verwenden, um beispielsweise anzugeben, dass der Typ Customer auch ein Typ des Basistyps "Person" ist. Sowohl im konzeptionellen Schema als auch im Speicherschema existiert außerdem ein BaseType-Attribut von EntityType, mit dem der Basistyp einer abgeleiteten Entität zugewiesen werden kann.

'Tabelle pro Hierarchie'-Modell

Bei einer auf dem "Tabelle pro Hierarchie"-Modell basierenden Vererbung werden mehrere Typen in der Hierarchie unter Verwendung derselben Datenbanktabelle angegeben. Bei diesem Modell gibt eine explizite Bedingung in der Mapping-Spezifikation den Typ in der Vererbungshierarchie an.

Der Tabelle wird eine Unterscheidungsspalte hinzugefügt, um die einzelnen Typen zu unterscheiden, und die Bedingung verweist auf einen zugewiesenen Wert der Spalte für den jeweiligen Typ. Die Bedingung kann beispielsweise angeben, dass der Wert der EntityType-Spalte für den Typ "Person" P oder für den Typ "Customer" C ist.

Im folgenden Mappingbeispiel wird das bedingte Mapping des Customer-Typs und des Person-Typs dargestellt.

<?xml version="1.0" encoding="utf-8"?>
<Mapping Space="C-S"
    xmlns:cdm="urn:schemas-microsoft-com:windows:storage:mapping:CS"
    xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">

  <EntityContainerMapping>
    <EntitySetMapping Name="CCustomer1">
      <EntityTypeMapping TypeName="CNorthwind.CCustomer">
        <MappingFragment StoreEntitySet="SParty1">
          <EntityKey>
            <ScalarProperty Name="PartyID" ColumnName="PartyID" />
          </EntityKey>
          <ScalarProperty Name="PartyName" ColumnName="PartyName" />
          <ScalarProperty Name="PartyTitle" ColumnName="Title" />
          <ScalarProperty Name="ContactName" ColumnName="ContactName" />
          <Condition Value="C" ColumnName="EntityType" />
        </MappingFragment>
      </EntityTypeMapping>
    </EntitySetMapping>

    <EntitySetMapping Name="CSupplier1">
      <EntityTypeMapping TypeName="CNorthwind.CSupplier">
        <MappingFragment StoreEntitySet="SParty1">
          <EntityKey>
            <ScalarProperty Name="PartyID" ColumnName="PartyID" />
          </EntityKey>
          <ScalarProperty Name="PartyName" ColumnName="PartyName" />
          <ScalarProperty Name="PartyTitle" ColumnName="Title" />
          <ScalarProperty Name="HomePage" ColumnName="HomePage" />
          <Condition Value="S" ColumnName="EntityType" />
        </MappingFragment>
      </EntityTypeMapping>
    </EntitySetMapping>

  </EntityContainerMapping>

</Mapping>

'Tabelle pro Typ'-Modell

Bei einer auf dem "Tabelle pro Typ"-Modell basierenden Vererbung wird der Basistyp bzw. der übergeordnete Typ in einer Tabelle gespeichert, für abgeleitete Typen werden jedoch zusätzliche Tabellen verwendet. Für abgeleitete Typen spezifische Felder sind nur in Tabellen vorhanden, die abgeleitete Typen darstellen. Das Mapping für die Entitäten in diesem Modell der Vererbung umfasst mehrere physische Tabellen. Die Typen in der Hierarchie werden durch Vorhandensein oder Nichtvorhandensein einer Zeile in einer Tabelle unterschieden. Den Schlüsseleigenschaften aller Tabellen wird derselbe Schlüsselwert zugewiesen.

Das BaseType-Attribut von EntityType kann in konzeptionellen Schemas und Speicherschemas verwendet werden, um die Vererbung vom Basistyp anzugeben. Der IsTypeOf<T>-Indikator in der Mappingspezifikation kann verwendet werden, um den Basistyp anzugeben und doppelt vorhandene Mappingsyntax zu vermeiden.

Im folgenden Mappingbeispiel werden zwei separate Mappings für den Customer-Typ und den Person-Typ dargestellt. Die ****TypeName-Attribute der EntityTypeMapping-Elemente unterscheiden den Person-Typ vom Customer-Typ. Für jeden Typ ist eine Tabelle vorhanden. Der Customer-Entitätstyp und die entsprechende Tabelle enthalten die NumYears-Eigenschaft und -Spalte, die im Basistyp nicht enthalten sind.

<?xml version="1.0" encoding="utf-8"?>
<Mapping Space="C-S" 
    xmlns:cdm="urn:schemas-microsoft-com:windows:storage:mapping:CS"
    xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">

  <EntityContainerMapping EntityContainerName="CNorthwind.LOBData">
    <EntitySetMapping Name="Person1">
      <EntityTypeMapping TypeName="CNorthwind.Person">
        <MappingFragment StoreEntitySet="Person">
          <ScalarProperty Name="PersonID" ColumnName="PersonID" />
          <ScalarProperty Name="Name" ColumnName="Name" />
        </MappingFragment>
      </EntityTypeMapping>
      <EntityTypeMapping TypeName="CNorthwind.Customer">
        <MappingFragment StoreEntitySet="Customer">
          <ScalarProperty Name="PersonID" ColumnName="PersonID" />
          <ScalarProperty Name="Name" ColumnName="Name" />
          <ScalarProperty Name="NumYears" ColumnName="NumYears" />
        </MappingFragment>
      </EntityTypeMapping>
    </EntitySetMapping>
  </EntityContainerMapping>

</Mapping>

Siehe auch

Aufgaben

Gewusst wie: Definieren eines Modells mit einer 'Tabelle pro Typ'-Vererbung (Entity Framework)
Gewusst wie: Definieren eines Modells mit 'Tabelle pro Hierarchie'-Vererbung (Entity Framework)

Konzepte

Entity Data Model-Typen
Hilfsmethoden (EDM)
Vererbung im Entity Data Model (Anwendungsszenarios)