Этот вопрос связан с другим вопросом, который я задал здесь ( Entity Framework 4.2 - Как реализовать наследование TPT с помощью значения первичного ключа, генерируемого базой данных? ) и должен просто уточнить, если мои предположения, касаются проблемы заявлено в теме, правы или нет.
Проблема (подробно):
- Я хочу использовать EF (4.1) для доступа к базе данных, которая уже существует
- база данных имеет некоторые ограничения относительно генерации значений первичного ключа для своих таблиц (есть UDF, который берет имя таблицы и возвращает следующий доступный идентификатор)
- Чтобы упростить для себя задачу, мой первый подход состоял в том, чтобы определить триггеры базы данных (перед вставкой), которые вызывают UDF, генерирующий ID, для установки нового идентификатора при вставке нового datarow
- Затем я установил свойства StoreGeneratedPattern соответствующих сущностей в csdl моего EDM на «Identity», чтобы вновь созданные идентификаторы были установлены в объектах сущностей после сохранения их в DB
Результат этого был:
Когда я создал новый объект-сущность, добавил его в DbContext и вызвал для него SaveChanges, соответствующий элемент данных был вставлен в базу данных, но объект не был обновлен с использованием нового идентификатора, созданного в базе данных. Я понял это, когда попытался сохранить больше сразу, которые имеют ассоциации друг с другом (parent-child), потому что свойства внешнего ключа дочерних объектов не могли быть установлены правильно, так как новый идентификатор родителя не был известен DbContext.
Вот почему я задал вышеупомянутый вопрос о наследовании TPT.
После нескольких дней исследований и попыток всего, что мне пришло в голову, решить эту проблему, я думаю, я понял, что это просто не может работать. Хотя документация перечисления StoreGeneratedPattern на MSDN и несколько пояснений в блогах предполагает, что StoreGeneratedPattern.Identity должен быть установлен для получения сгенерированного значения, когда БД генерирует значение при вставке новой строки, это не верно для первичных ключей в сочетании с триггерами базы данных.
После долгих размышлений об этом мне кажется вполне логичным, поскольку EF нужен какой-то критерий для извлечения значений, сгенерированных базой данных, и я думаю, что в большинстве случаев это будет идентичность сущности. Для столбцов базы данных, для которых задано автоинкремент (или идентификатор-столбца, ...), это может быть проблемой, поскольку СУБД предоставляет некоторые функции для извлечения последнего вставленного значения-идентификатора (например, @@ identity в MSSQL). Но при использовании триггера для генерации нового значения идентификатора EF, очевидно, не знает, как запросить вновь вставленную строку (и я не могу представить какой-либо хороший независимый от БД способ сделать это либо).
Итак, мой актуальный вопрос: верны ли предположения выше, или я упускаю здесь что-то важное?
Заранее спасибо за любые разъяснения / вдохновение по этому вопросу.
Редактировать (следующий вопрос):
После прочтения ответа от Ладислава возникает другой вопрос:
Если я устанавливаю StoreGeneratedPattern в CSDL, нужно ли мне устанавливать для него такое же значение в SSDL (и наоборот)? Патч для дизайнера edm подразумевает, что это так, потому что он автоматически синхронизирует StoreGeneratedPattern в SSDL при изменении его в CSDL (через конструктор).