Наследование (модель EDM)
В модели Entity Data Model (EDM) наследование позволяет расширять функции типов при помощи производного типа.
Обычно модель, которую использует приложение, имеет много разных типов. Некоторые типы сущности моделируют в приложениях для бизнеса разные концепции, например «клиент» и «заказ» . Эти типы данных не имеют общих членов, однако существуют другие типы, которые больше похожи друг на друга. В качестве примера рассмотрим типы «клиент» и «служащий». Хотя эти типы моделируют разные концепции, у них есть базовая общность: оба типа представляют людей, участвующих в деловых отношениях, и оба имеют свойства для хранения таких сведений, как ФИО, адрес и номер телефона.
В модели EDM наследование позволяет одному типу быть производным другого типа. Например, типы Employee
и Customer
могут наследовать от типа Contact
. В данном случае Contact
называется базовым типом, а Employee
и Customer
называются производными типами.
Наследование не обязательно ограничивается одним уровнем: производный тип может быть базовым типом другого типа сущности. Например, тип Employee
является базовым типом Manager
, тип Customer
является базовым типом PreferredCustomer
и так далее. Таким образом строятся иерархии наследования.
Как и среда CLR, система EDM поддерживает только одиночное наследование типов данных. Тип сущности может наследовать свойства напрямую только от одного супертипа.
![]() |
---|
Поскольку в системе EDM не реализуются методы, наследование методов не поддерживается. Вспомогательные методы в системе EDM реализованы в разделяемых классах. Дополнительные сведения см. в разделе Вспомогательные методы (модель EDM). |
Примеры наследования
В следующих примерах демонстрируется частичная спецификация языка CSDL для описанной ранее иерархии наследования:
<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 -->
Одним из предназначений наследования является совместное использование несколькими типами фундаментальной структуры. Другой причиной использования наследования является расширяемость. Даже после реализации и внедрения в приложение иерархии наследования разработчики могут расширять типы при помощи наследования.
Принцип полиморфизма или заменяемости значений в объектно-ориентированном программировании базируется на наследовании. Каждый экземпляр производного типа данных также является экземпляром своего базового типа. Например, если тип Manager
является производным типа Employee
, то каждый экземпляр типа Manager
также является экземпляром типа Employee
. При запросе всех сотрудников (базовый тип) возвращаются также и все менеджеры (производный тип).
Дополнительные сведения о наследовании см. в разделах Как Задать модель с наследованием «одна таблица на тип» и Как определить модель с наследованием типа «одна таблица на иерархию» (платформа Entity Framework).
Реализация наследования
По определению в языке CSDL иерархия наследования должна реализовываться в таблицах базы данных, в которых хранятся данные приложения, построенного по модели EDM. Есть несколько способов структурирования типов, составляющих иерархию наследования, в таблицах базы данных.
Во всех реализациях ключевая структура базовых и производных типов должна быть одинаковой. То есть если тип Customer
является производным типа Person
, оба типа, Customer
и Person
, должны указывать одинаковое ключевое свойство или свойства.
При реализации наследования в нескольких таблицах ключевому свойству назначается одинаковое значение в более чем одной таблице, чтобы идентифицировать производные типы как экземпляры базовых типов.
Реализации наследования в спецификации сопоставления могут использовать индикатор IsTypeOf<T> в EntityTypeMapping, чтобы указать, что, например, тип Customer
также является типом базового типа Person. В концептуальной схеме и схеме хранения существует также атрибут BaseType объекта EntityType, который можно использовать, чтобы обозначать базовый тип производной сущности.
Модель «одна таблица на иерархию»
В наследовании, основанном на модели «одна таблица на иерархию», несколько типов в иерархии определяются с использованием одной таблицы базы данных. В этой модели тип в иерархии наследования идентифицируется явным условием в спецификации сопоставления.
Столбец дискриминаторов включается в эту таблицу, чтобы обозначать каждый тип, а условие ссылается на назначенное значение столбца для каждого типа. Например, условие может указывать, что значение столбца EntityType
равно P
для типа Person, а для типа Customer — C
.
В следующем примере сопоставления демонстрируется условное сопоставление типов Customer
и Person
.
<?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>
Модель «одна таблица на тип»
В наследовании, основанном на модели «одна таблица на тип», базовый или исходный тип хранится в одной таблице, а для производных типов используются дополнительные таблицы. Поля, характерные для производных типов, появляются только в таблицах, в которых хранятся производные типы. Сопоставление сущностей в этой модели наследования охватывает несколько физических таблиц. Типы в иерархии отличаются наличием или отсутствием строки в таблице. Ключевому свойству во всех таблицах назначается одинаковое ключевое значение.
Атрибут BaseType типа сущности EntityType можно использовать в концептуальной схеме или схеме хранения для обозначения наследования от базового типа. Индикатор IsTypeOf<T> можно использовать в спецификации сопоставления для обозначения базового типа и устранения повторяющегося синтаксиса сопоставления.
В следующем примере сопоставления показаны два отдельных сопоставления для типов Customer
и Person
. В атрибутах TypeName элементов EntityTypeMapping и состоит отличие типов Person
и Customer
. Для каждого типа имеется своя таблица. Тип и таблица сущности Customer
содержат свойство и столбец NumYears
, которые не включены в базовый тип.
<?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>
См. также
Задачи
Как задать модель с наследованием «таблица для типа» (платформа Entity Framework)
Как определить модель с наследованием типа «одна таблица на иерархию» (платформа Entity Framework)
Основные понятия
Типы модели EDM
Вспомогательные методы (модель EDM)
Наследование в модели EDM (сценарии приложений)