Entity Framework - абстрактный базовый класс без сопоставления с таблицей DB
У меня есть ситуация, когда у меня есть 4-5 очень похожих классов, которые я бы хотел повторно использовать для использования абстрактного базового класса. Идея этого заключалась в том, чтобы позволить методам, которые могут быть использованы каждым классом при соблюдении принципов СУХОЙ.
Проблема в том, что эти классы являются классами Entity, созданными из EF4, и каждый раз, когда я пытаюсь изменить свою модель, она, похоже, сломается.
Какой лучший/рекомендуемый метод, чтобы добавить базовый класс в мою EF-модель и сделать существующие классы в модели наследовать от этого в качестве базы? На данный момент у меня нет проблем с добавлением базового класса, придающего ему свойство идентификатора, которое, как ему кажется, требуется, и затем создание наследования, но EF затем стонет
'Error 3024: Problem in mapping fragments starting at line 18563:Must specify mapping for all key properties (MyBaseType.ID) of the EntitySet MyBaseType.'
В этой ситуации я не хочу, чтобы базовый тип сохранялся в БД, чисто используемый в качестве контейнера для базовых методов, общих для всех классов, которые наследуются от него. Мне кажется, что я пропустил что-то простое здесь, но я не могу, чтобы жизнь меня видела.
Любые идеи о том, как добавить в базовый класс таким образом? Или я должен просто добавлять базовый класс в код и как-то обходить модель?
EDIT: В качестве дополнительной информации возьмите пример, в котором говорят 3 типа: MortageApplicationForm, BankAccountApplicationForm и CreditCardApplication. В настоящее время они хранятся в трех разных таблицах с набором различных полей. То, что я пытаюсь сделать, - создать базовый класс, который называется "Форма", который будет иметь общие поля в нем.
На простом уровне скажите, что каждая таблица имеет поле идентификатора первичного ключа, называемое "CreditCardFormID", "BankAccountFormID" и т.д. Что бы я хотел сделать, это создать базовый класс "Form" с идентификатором свойства, который для случая из одной таблицы будет отображаться "CreditCardFormID" и другой "BankAccountFormID".
Я рад сделать это сопоставление в частичных классах (поскольку я не хочу сохранять идентификатор в БД), я просто хочу использовать его в коде, поэтому я могу писать общие методы для таких вещей, как LoadForm (int ID) без необходимости писать огромные переключатели для каждого типа сущности или конкретные методы для каждого типа сущности.
Ответы
Ответ 1
Мне удалось найти работу для этого, слегка перефразируя вещи. Во-первых, у меня не было времени на доработку модели (которая, я думаю, была бы лучшим решением), слишком большая часть системы уже была разработана с существующей структурой, чтобы разорвать все это на этом месте.
До сих пор решение заключалось в создании статического вспомогательного класса, который бы содержал бизнес-логику, которая является общей в моем примере, тремя разными типами учетных записей.
Это было связано с интерфейсом "IAccount", позволяющим вспомогательному классу принимать экземпляр IAccount в качестве параметра (позволяющий передавать какой-либо конкретный тип учетной записи.) Этот интерфейс содержал все общие свойства по 3-4 конкретным классам. Важно отметить, что для создания общих методов, которые я мог бы назвать всеми классами, я не смог использовать какие-либо другие свойства, специфичные для этого класса.
В рамках вспомогательных методов мне нужно было переключить конкретный экземпляр XYZEntities на более общий объект ObjectContext и затем использовать явно такие методы, как AddObject, а не AddBankAccountForm, AddCreditCardForm и т.д. Это включало крошечный бит GetType() для обеспечения того, чтобы объект был передан правильному объекту ObjectSet, но, похоже, работает по своему желанию.
Ответ 2
Для этого есть 3 шаблона:
- Таблица для иерархии классов. Все конкретные типы в наследственной иерархии хранятся в одной таблице.
- Таблица для каждого типа. Каждый тип в наследовании хранится в собственной таблице.
- Таблица для конкретного класса. Таблица для каждого конкретного класса, но нет таблицы для абстрактного класса.
В вашем случае с существующими таблицами класс Table per Concrete выглядит наилучшим образом.
В этой книге есть хорошее описание этих вариантов