#entity-framework
#entity-framework
Вопрос:
Использование EF 4.0 с обновлением 4.1 для POCO / code-first.
Хорошо, итак, у меня есть модель предметной области, где type Car
имеет в коллекции несколько объектов типа Part
. Итак, отношение один: много.
HasMany(v => v.Parts)
.WithRequired()
.HasForeignKey(v => v.CarId)
.WillCascadeOnDelete();
Проблема в том, что это требует от меня добавления CarId
свойства к моему Part
типу. Это приводит к утечке информации ORM в мою модель домена, что плохо. Маркировка всего виртуального достаточно раздражает.
Просмотр комментария к XML-документу для HasForeignKey()
метода говорит об этом:
Настраивает связь для использования свойств внешнего ключа, которые предоставляются в объектной модели. Если свойства внешнего ключа не представлены в объектной модели, тогда используйте метод Map.
Это здорово и все такое. Но это приводит к ситуации с подвохом 22, потому что, если я реорганизую свой Part
тип, удаляя CarId
ненужное мне свойство, и обновляю свой EF model builder, чтобы не беспокоиться о сопоставлении этого свойства. Тогда, как вы можете себе представить, это означает, что я не могу вызвать HasKey()
для определения составного ключа, ala:
HasKey(v => new { v.CarId, v.PartId });
HasKey()
похоже, что не поддерживается определение ключей на основе лямбд, не являющихся свойствами.
Каково здесь решение?
Комментарии:
1. Я думаю, что заголовок вашего вопроса должен быть таким: «Как определить первичный ключ, не предоставляя все столбцы первичного ключа в качестве свойств в модели?» Разве это не проблема на самом деле? Убивая
CarId
, вы хотите удалить не только свойство FK (что легко), но и часть вашего сложного PK (что, вероятно, невозможно).2. Вы правы. Ключевым моментом здесь является то, что я не хочу лишних «обратных ссылок» в моей модели домена. Модели домена они не нужны, и они просто становятся проблемой для синхронизации. Я удивлен, что EF, похоже, требует загрязнения моей доменной модели обратными ссылками, которые касаются исключительно СУБД.
3. Вам не нужны обратные ссылки в EF, предоставлять их необязательно. Ваша проблема в том, что у вас есть составной первичный ключ, и часть его является внешним ключом. Обычно вы могли бы избавиться от свойства внешнего ключа, но не в вашем случае, потому что оно одновременно является частью PK. И вы не можете удалить PK из класса модели. Вашим лучшим вариантом было бы создать
PartId
только первичный ключ, затем вы могли бы удалитьCarId
. Это в основном то, что предложил хазимдикенли в своем ответе.
Ответ №1:
Если вам абсолютно не нравится иметь свойства внешнего ключа в вашей модели, вы могли бы удалить соглашение об обнаружении свойств FK, чтобы избежать того, что EF автоматически помечает свойства как свойства FK …
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions
.Remove<NavigationPropertyNameForeignKeyDiscoveryConvention>();
}
… и затем просто не указывайте свойство FK в своем сопоставлении:
HasMany(v => v.Parts)
.WithRequired()
.WillCascadeOnDelete();
Вам все еще нужно CarId
в вашей модели, потому что это часть первичного ключа, но таким образом он больше не действует как свойство внешнего ключа.
Просто идея, я не уверен, работает ли это.
Ответ №2:
Ну, а как насчет добавления нового ключевого поля в таблицу CarParts, такого как CarPartId, чтобы вам не понадобился составной ключ. (Поддержка составных ключей не так уж хороша при работе с ORM.)