Entity Framework - Code First: сопоставление с дочерними / необязательными свойствами Mutliple того же типа - PullRequest
0 голосов
/ 21 декабря 2011

Моя модель домена имеет класс пользователя и адреса

public User
{
   int Id
   Address PrimaryAddress
   Address SecondaryAddress
   and some other Properties
}

Оба являются необязательными, но каждый адрес должен иметь пользователя. Codeirst Mapping выглядит как

modelBuilder.Entity<User>()
   .HasOptional(u => u.PrimaryAddress)
   .WithRequired()
   .WillCascadeOnDelete(false);
modelBuilder.Entity<User>()
   .HasOptional(u => u.SecondaryAddress)
   .WithRequired()
   .WillCascadeOnDelete(false);

Но это не дает желаемого результата. Я ожидаю два (int, null) столбца для пользовательской таблицы, указывающие на адресную таблицу. И таблица адресов, вероятно, имеет столбец UserId (внешний ключ, int, не ноль). Но с кодом выше Столбец «ID» Address, действующий как PK и FK (указывает на таблицу User).

1 Ответ

1 голос
/ 21 декабря 2011

Вы отобразили отношение один-к-одному, и это именно то, что вы видите в базе данных.Короче говоря, то, чего вы хотите достичь, невозможно.

Особенно та часть, где Address должен иметь User, не может работать, потому что у вас есть два навигационных свойства для объекта User, которые приведут к двум различным столбцам FK в таблице Address, и им придетсябыть обнуляемым, в противном случае каждый адрес должен быть как первичным, так и вторичным для некоторого пользователя.

Корректная модель сопоставляется с сопоставлением по умолчанию (не требуется плавного сопоставления), поскольку она создает пользователя с двумя FK для адресации.Адрес находится в двух отношениях «один ко многим» с пользователем, потому что теоретически у вас может быть несколько пользователей с одним и тем же адресом.

Другой вариант - смоделировать отношение «многие ко многим», где таблица соединений будет смоделирована как сущность с дополнительным свойством AddressType.

Если вы действительно хотите следовать своей текущей модели, вынеобходимо использовать это:

modelBuilder.Entity<User>()
    .HasOptional(u => u.PrimaryAddress)
    .WithOptionalPrincipal()
    .WillCascadeOnDelete(false);
modelBuilder.Entity<User>()
    .HasOptional(u => u.SecondaryAddress)
    .WithOptionalPrincipal()
    .WillCascadeOnDelete(false);

Это создаст два дополнительных столбца FK в таблице Address, и само отношение будет одно-ко-многим (у одного пользователя может быть много адресов).Причина заключается в том, что принудительное использование «один к одному» требует уникальности FK, а текущая версия EF не поддерживает уникальные ключи.Вы можете добавить уникальные ограничения на столбцы FK при постобработке (либо через пользовательский инициализатор БД , либо с помощью EntityFramework.Migrations), но это приведет к другим проблемам.В SQL допустимое значение NULL считается допустимым значением, поэтому при наличии уникального ограничения на столбец, допускающий значение NULL, только нулевая запись может иметь только одна запись.

...