У нас есть база данных, в которой одна таблица содержит записи, которые могут быть дочерними для нескольких других таблиц. Он имеет "мягкий" внешний ключ, состоящий из идентификатора владельца и имени таблицы. Этот (анти) шаблон известен как "полиморфные ассоциации". Мы знаем, что это не лучший дизайн базы данных, и мы будем менять его в свое время, но не в ближайшем будущем. Позвольте мне показать упрощенный пример:
Оба Event
, Person
и Product
имеют записи в комментарии. Как вы видите, жестких ограничений FK нет.
В Entity Framework можно поддержать эту модель, подделав Comment
в EventComment
и т.д., и пусть Event
имеет коллекцию EventComments
и т.д.:
Подклассы и ассоциации добавляются вручную после создания базовой модели из базы данных. OwnerCode
является дискриминатором в этой модели TPH. Обратите внимание, что Event
, Person
и Product
- совершенно разные объекты. Нет смысла иметь для них общий базовый класс.
Это первая база данных. Наша реальная модель работает так, без проблем.
OK. Теперь мы хотим перейти к коду в первую очередь. Поэтому я начал обратную разработку базы данных в первую модель кода (EF Power Tools) и продолжил создание подклассов и отображение ассоциаций и наследования. Пробовал подключиться к модели в Linqpad. Это когда начались неприятности.
При попытке выполнить запрос с помощью этой модели он выдает InvalidOperationExeception
Компонент внешнего ключа "OwnerId" не является объявленным свойством типа "EventComment". Убедитесь, что он не был явно исключен из модели и что он является допустимым примитивным свойством.
Это происходит, когда у меня есть двунаправленные ассоциации, а OwnerId
отображается как свойство в Comment
. Отображение в моем классе EventMap
(EntityTypeConfiguration<Event>
) выглядит следующим образом:
this.HasMany(x => x.Comments).WithRequired(c => c.Event)
.HasForeignKey(c => c.OwnerId);
Итак, я попытался сопоставить ассоциацию без OwnerId
в модели:
this.HasMany(x => x.Comments).WithRequired().Map(m => m.MapKey("OwnerId"));
Это выдает a MetaDataException
Указанная схема недействительна. Ошибки: (10,6): ошибка 0019: каждое имя свойства в типе должно быть уникальным. Название свойства "OwnerId" уже определено. (11,6): ошибка 0019: каждое имя свойства в типе должно быть уникальным. Имя свойства "OwnerId" уже определено.
Если я удалю две из трех ассоциаций сущность-комментарий, это нормально, но, конечно, это не излечение.
Дополнительная информация:
- Можно создать рабочую модель DbContext ( "второй код" ) из edmx, добавив элемент генератора DbContext. (пока это будет работать).
- Когда я экспортирую рабочую кодовую первую модель (с одной ассоциацией) в edmx (
EdmxWriter
), ассоциация, похоже, находится в модели хранения, тогда как в исходном edmx они являются частью концептуальной модели.
Итак, как я могу создать этот код модели во-первых? Я думаю, что ключевым является то, как инструктировать код - сначала сопоставить ассоциации в концептуальной модели, а не с моделью хранения.