Я хочу использовать EF (4.2) в следующем сценарии:
- База данных уже существует (поэтому я выбрал подход, основанный на базе данных), и это база данных SQL Anywhere.
- Я хочу использовать невежественные бизнес-объекты, поэтому я использую шаблон
DbContext
для генерации POCO
классов из EDM. - Существует одна простая иерархия наследования среди моих сущностей:абстрактная базовая сущность и две конкретные производные сущности.
- В базе данных имеется одна таблица для каждого типа иерархии наследования (Table-Per-Type Strategy).
- Каждая из этих трех таблиц имеетстолбец первичного ключа (
Id
, тип: integer
), и привязка конкретного объекта к базовому объекту выполняется с помощью одинакового Id
в обеих таблицах (это означает, что первичный ключ (Id
)) таблиц конкретных типов одновременно является внешним ключом к базовой таблице; я думаю, что это довольно распространенный подход).
Мне пришлось определить Inheritance вручную в конструкторе, sincПомощник по EDM не распознает автоматически, то есть хочет иметь связь наследования между описанными объектами.
До этого момента не было более серьезных проблем.Теперь к проблеме: есть ограничение для базы данных, которую я использую: Primarykey
значения должны генерироваться базой данных, используя функцию базы данных.Я хочу вызвать эту функцию в before-insert-trigger
, определенном в base-table
.
. Чтобы структура сущностей знала, что значение генерируется базой данных, я устанавливаю свойство StoreGeneratedPattern
* 1029.* Свойство от base-entity
до Identity
(как я понял, это способ сказать EF получать сгенерированное значение после вставки нового экземпляра сущности).
Когда я создаю новый экземплярпроизводного объекта, добавьте его к соответствующему DbSet
из DbContext
и вызовите SaveChanges
в контексте, выдается DbUpdateException
, заявляя, что ограничение foreignkey
нарушено.Проверяя журнал запросов к базе данных, я вижу, что базовая сущность была вставлена в базовую таблицу, но при вставке строки в производную таблицу возникает вышеупомянутая ошибка, поскольку она, очевидно, не использует вновь сгенерированный Id
новой записи в базовой таблице.
Поскольку я не думаю, что я могу многое сделать на уровне базы данных против этого, возникает вопрос, можно ли настроить EDM или DbContext (илиизменено), чтобы сначала вставить базовую строку, затем взять сгенерированный Id
и использовать его для вставки производной строки.
Я знаю, что есть несколько способов избежать этой ситуации (не используя наследование, используя сохраненныйпроцедура для вставки новой производной сущности, вызывающая db-функцию, генерирующую id, перед вставкой и установки свойства Id
для самой сущности), но на данный момент описанное выше поведение будет наиболее предпочтительным, поэтому я хочуубедитесь, что не пропустили что-то, прежде чем принять решение о каком-либо "плане B".приветствуется.
Вот код триггера:
ALTER TRIGGER "TRG_GENERATE_ID" before insert order 1 on
BASE_TABLE
referencing new as NewEntry
for each row
begin
declare NewID integer;
set NewID = F_GET_NEW_ID('BASE_TABLE', NewEntry.SOME_OTHER_ID);
set NewEntry.ID = NewID
end
Функция "F_GET_NEW_ID" вызывается в триггере для генерации нового идентификатора для новой записибазовый стол.Он имеет два параметра: «Имя таблицы» -> Имя таблицы, для которой должен быть создан новый идентификатор, и второй параметр, который принимает значение стандартного столбца во всех таблицах базы данных (требуется для создания нового идентификатора.).