3

В настоящее время я занимаюсь уборкой довольно большой базы данных. Часть базы данных имеет отношение, которое является сопоставлением от одного к ноль-одному. В частности:Сопоставление одно-нуля или одного с EF7

User -> UserSettings 

Не все пользователи будут иметь пользовательские настройки, но пользовательские настройки не могут существовать без пользователя. К сожалению, таблицы уже существуют. User имеет идентификатор ПК. UserSettings имеет идентификатор PK и столбец User_Id_Fk, который на данный момент не является истинным FK (отношения не определены).

Я в процессе исправления и сделал это с точки зрения БД через SQL и подтвердил с помощью тестов. (Добавлено ограничение FK. Добавлено уникальное ограничение на User_Id_Fk.) Все это было сделано в таблице UserSettings. (Примечание: я не использую EF Migrations здесь. Мне нужно вручную написать SQL в этот момент времени.)

Однако теперь мне необходимо подключить существующее приложение для правильной обработки этого нового сопоставления. Приложение использует ASP.NET Core 1.0 и EF7. Вот (сокращенные) версии существующих моделей данных.

public class User 
{ 
    public int Id { get; set; } 

    public virtual UserSettings UserSettings { get; set; } 
} 

public class UserSettings 
{ 
    public int Id { get; set; } 

    [Column("User_Id_Fk")] 
    public int UserId { get; set; } 

    [ForeignKey("UserId")] 
    public virtual User User { get; set; } 
} 

У меня есть этот свободный Mapping, а также:

builder.Entity<UserSettings>() 
      .HasOne(us => us.User) 
      .WithOne(u => u.User) 
      .IsRequired(false); 

Когда я иду, чтобы запустить приложение и доступ к этим элементам в базе данных, я получаю эту ошибку, затем с загадочным набором сообщений, который имеет нет информации, относящейся непосредственно к моему заявлению .:

ArgumentNullException: Value cannot be null. 
Parameter name: navigation 
Microsoft.Data.Entity.Utilities.Check.NotNull[T] (Microsoft.Data.Entity.Utilities.T value, System.String parameterName) <0x10d28a650 + 0x00081> in <filename unknown>, line 0 

После проведения исследований, кто-то упомянул, что идентификатор класса UserSettings должен быть таким же, как внешний ключ, Лик е так:

public class UserSettings 
{ 
    [Key, ForeignKey("User")] 
    public int Id { get; set; } 

    public virtual User User { get; set; } 
} 

Я на самом деле не это как вариант в качестве БД используется для других приложений, которые я не имеют никакого контроля над в этой точке. Итак, я застрял здесь? Должен ли я просто поддерживать отображение 1: много (что может произошло, хотя это не так) и не имеют надлежащих ограничений для отображения 1: 0..1?

Обновление Рассматривая ответ octavioccl ниже, я пробовал его без каких-либо успехов. Однако я удалил User из картографирования в UserSettings (но я оставил UserId). Все, казалось, работало, насколько я могу судить. Однако я действительно запутался в том, что происходит здесь, и если это даже правильный ответ, или мне просто повезет.

ответ

3

Удалить аннотации данных и попытаться с этими конфигурациями:

builder.Entity<UserSettings>() 
      .Property(b => b.UserId) 
      .HasColumnName("User_Id_Fk"); 

builder.Entity<User>() 
      .HasOne(us => us.UserSettings) 
      .WithOne(u => u.User) 
      .HasForeignKey<UserSettings>(b => b.UserId); 

От EF Core documentation:

При настройке внешнего ключа вам необходимо указать зависимый тип лица - обратите внимание на общий параметр при условии до HasForeignKey в списке выше. В связи один-ко-многим ясно, что предприятия с эталонной навигацией является зависимым и один с коллекцией является основнымами.Но это не так в отношениях один-к-одному, поэтому необходимо явно определить его.

Пример, который представлен в quoted link (Blog - BlogImage) в значительной степени то же самое, что вы пытаетесь достичь.

Если решение, которое я покажу выше, не работает, тогда вы должны проверить, разрешает ли User_Id_Fk столбец null. Если это так, измените тип свойства FK на int?:

public class UserSettings 
{ 
    public int Id { get; set; } 

    public int? UserId { get; set; } 

    public virtual User User { get; set; } 
} 
+0

Благодарим за отзыв. К сожалению, нет. Я немного смущен вашим ответом, когда у пользователя должен быть только нулевой или один пользовательский набор. Я не понимаю, как ваше решение достигает этого. (Это выходит за рамки того факта, что я все еще получаю ту же ошибку.) Могли бы вы дать разъяснения? Благодаря! – JasCav

+0

Добавлено редактирование/обновление. – JasCav

+0

Я видел ваше обновление сейчас, я думаю, что это работает, потому что EF видит теперь ваши отношения как одного для многих, а не как одного к одному. Когда вы объявляете только одно свойство навигации между связанными объектами, EF по умолчанию создает от одного до многих, я также путаю то, как работает ваша текущая модель, потому что, если у вас есть столбец FK в таблице UserSettings, в случае, если EF видит от одного до многих, свойство навигации коллекции должно быть объявлено в 'User', а не в качестве ссылочного навигационного свойства. В самом деле, очень смутно, позвольте мне снова подумать снова, если я найду что-то разумное, я сообщу – octavioccl

Смежные вопросы