Моделирование полиморфных ассоциаций база данных сначала против кода сначала
У нас есть база данных, в которой одна таблица содержит записи, которые могут быть дочерними для нескольких других таблиц. Оно имеет "мягкий" внешний ключ, состоящий из владельцаИдентификатор и имя таблицы. Этот (анти) шаблон известен какполиморфные ассоциации ", Мы знаем это'Это не лучший дизайн базы данных, и мы изменим его в свое время, но не в ближайшем будущем. Позвольте мне показать упрощенный пример:
И то и другое ,Event
Person
, а такжеProduct
есть записи в комментариях. Как видите, жестких ограничений FK нет.
В Entity Framework можно поддерживать эту модель путем создания подклассовComment
вEventComment
и т.д. и пустьEvent
естьEventComments
коллекция и т.д .:
Подклассы и ассоциации добавляются вручную после генерации базовой модели из базы данных.OwnerCode
дискриминатор в этомтонн в час модель. Обратите внимание, чтоEvent
Person
, а такжеProduct
это совершенно разные сущности. Не имеет смысла иметь общий базовый класс для них.
Это база данных в первую очередь. Наша реальная модель работает так, без проблем.
ХОРОШО. Теперь мы хотим перейти к первому коду. Поэтому я начал реинжиниринг базы данных в первую модель кода (EF Power Tools) и продолжал создавать подклассы и отображать ассоциации и наследование. Пытался подключить к модели в Linqpad. Тот'когда начались проблемы.
При попытке выполнить запрос с этой моделью он выдаетInvalidOperationExeception
Компонент внешнего ключаOwnerId» не является объявленным свойством типаEventComment», Убедитесь, что он не был явно исключен из модели и является допустимым примитивным свойством.
Это происходит, когда у меня есть двунаправленные ассоциации иOwnerId
отображается как свойство вComment
, Отображение в моемEventMap
учебный класс (EntityTypeConfiguration
) выглядит так:
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"));
Это кидаетMetaDataException
Указанная схема недействительна. Ошибки: (10,6): ошибка 0019: каждое имя свойства в типе должно быть уникальным. Имя свойства 'OwnerId» был уже определен. (11,6): ошибка 0019: каждое имя свойства в типе должно быть уникальным. Имя свойства 'OwnerId» был уже определен.
Если я удаляю две из трех ассоциаций с комментариями, это нормально, но, конечно,Это не лекарство.
Некоторые дальнейшие детали:
Можно создать рабочую модель DbContext ("код второй ") из edmx, добавив элемент генератора DbContext. (это будет обходной путь в настоящее время).Когда я экспортирую рабочую модель с первым кодом (с одной ассоциацией) в edmx (EdmxWriter
) связь, по-видимому, существует в модели хранения, тогда как в исходном edmx они являются частью концептуальной модели.Итак, как я могу создать эту модель кода в первую очередь? Я думаю, что ключ заключается в том, чтобы сначала дать коду команду сопоставить ассоциации в концептуальной модели, а не в модели хранения.