12

У меня есть следующие объекты:Вставка зависимого общества с ApplicationUser

public class ApplicationUser : IdentityUser 
{ 
    ... 
    public int? StudentId { get; set; } 
    public virtual Student Student { get; set; } 
} 

public class Student 
{ 
    public int Id { get; set; } 
    public string UserId { get; set; } 
    public virtual ApplicationUser User { get; set; } 
} 

И я пытаюсь создать новый пользователь приложения и студент, так что я делаю это:

var user = new ApplicationUser() { 
    Name = "test", 
    UserName = "test", 
    Student = new Student() 
}; 

var result = await userManager.CreateAsync(user, "test12345!"); 

Результата является успешным, два объекта вставляются в базу данных, но Student.UserId имеет значение

Как вставить оба объекта и их отношения?

Я попытался установить student.UserId = user.Id, но затем я получаю исключение с этим сообщением: «Невозможно определить правильный порядок для зависимых операций»

+0

как они отображаются? Student.UserId не может быть таким же, как User.Id (я предполагаю), потому что UserId является строковым типом, и когда Id является сгенерированной базой данных, это должно быть числовое значение. edit: когда пользователь.Id действительно является строковым значением, возникающая ошибка может быть исправлена ​​с использованием HasOptional(). WithOptionalDependant() – DevilSuichiro

+0

Да, Student.UserId совпадает с User.Id, ApplicationUser наследует от IdentityUser, а IdentityUser по умолчанию имеет строку Id – Escobar5

+0

Кроме того, модель создана правильно, в базе данных у меня есть правильные внешние ключи, это просто, что значение не установлено – Escobar5

ответ

8

Проблема и решение приводятся здесь One-to-one relationsip with optional dependent end using default conventions и здесь EF Code First - 1-to-1 Optional Relationship. Но позвольте мне добавить что-то к теме.

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

Красота первого подхода EF-кода заключается в том, что вам не нужно думать о таких вещах. Не пытайтесь создавать свои POCO, как таблицы db. За исключением первичного ключа, не используйте свойства xxxId. Используйте правильно настроенные навигационные свойства , чтобы выразить отношения между вашими объектами и позволить EF заботиться о дизайне db.

Со всем, что в виду:

Во-первых, удалить StudentId свойство из ApplicationUser класса и UserId свойство из Student класса. Обратите внимание, что это приведет к удалению столбца StudentId из соответствующей таблицы db, поэтому вы можете подумать о том, чтобы начать с нового db или использовать миграции.

Затем используйте следующую конфигурацию:

modelBuilder.Entity<ApplicationUser>() 
    .HasOptional(u => u.Student) 
    .WithRequired(s => s.User).Map(a => a.MapKey("UserId")); 

и ваша проблема должна быть решена.

+0

Этот вопрос сработал, у меня есть другой вопрос, это может быть достигнуто только с помощью Fluent API или есть ли способ сделать то же самое с Data Annotations? – Escobar5

+0

AFAIK, только Fluent API. –

3

Вы ищете для одного (ноль или один) вид отношений между учеником и пользователем приложения. Таким образом, для одного пользователя может быть или не быть учеником.

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

modelBuilder.Entity<ApplicationUser>() 
.HasKey(t => t.StudentId); 


// Map one-to-zero or one relationship 
modelBuilder.Entity<ApplicationUser>() 
    .HasRequired(t => t.Student) 
    .WithOptional(t => t.ApplicationUser); 

Вместо если вы ищете 12:59 отношения

modelBuilder.Entity<ApplicationUser>() 
    .HasKey(t => t.StudentId); 

modelBuilder.Entity<Instructor>() 
    .HasRequired(t => t.Student) 
    .WithRequiredPrincipal(t => t.ApplicationUser); 

В обоих случаях вам может не потребоваться Id на обоих образованиях. В качестве примечания конца, пожалуйста, поделитесь классом сопоставления для обоих, если это возможно.

+0

Я пробовал в обоих направлениях, структура базы данных выглядит нормально, но когда я добавляю Студент в ApplicationUser, и попробуйте добавить его в dbcontext, он говорит, что поле UserId (в студенте) требуется. – Escobar5

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