Подтвердить что ты не робот

Моделирование базы данных полиморфных ассоциаций - сначала против первого кода

У нас есть база данных, в которой одна таблица содержит записи, которые могут быть дочерними для нескольких других таблиц. Он имеет "мягкий" внешний ключ, состоящий из идентификатора владельца и имени таблицы. Этот (анти) шаблон известен как "полиморфные ассоциации". Мы знаем, что это не лучший дизайн базы данных, и мы будем менять его в свое время, но не в ближайшем будущем. Позвольте мне показать упрощенный пример:

enter image description here

Оба Event, Person и Product имеют записи в комментарии. Как вы видите, жестких ограничений FK нет.

В Entity Framework можно поддержать эту модель, подделав Comment в EventComment и т.д., и пусть Event имеет коллекцию EventComments и т.д.:

enter image description here

Подклассы и ассоциации добавляются вручную после создания базовой модели из базы данных. 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 они являются частью концептуальной модели.

Итак, как я могу создать этот код модели во-первых? Я думаю, что ключевым является то, как инструктировать код - сначала сопоставить ассоциации в концептуальной модели, а не с моделью хранения.

4b9b3361

Ответ 1

Я лично использую Database сначала при использовании EF на любой схеме, которая является таким уровнем сложности. Сначала у меня были проблемы со сложными схемами в отношении кода. Возможно, более новые версии немного лучше, но беспокоиться о том, как пытаться создавать сложные отношения, кажется менее прямолинейным, а затем позволяет движку генерировать его для вас. Также, когда отношения становятся такими сложными, я стараюсь не пытаться генерировать его с помощью EF и пытаться использовать хранимые процедуры для более легкого устранения проблем с узкими местами производительности, которые могут возникнуть.