Entity Framework, сохраняющий данные в ассоциациях «один к одному»

#entity-framework #entity-framework-4.1 #foreign-key-relationship #one-to-one

#entity-framework #entity-framework-4.1 #взаимосвязь внешнего ключа #один к одному

Вопрос:

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

Вот как выглядят модели:

 public class Team
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int OwnerID { get; set; }
    public virtual User Owner { get; set; }
}

public class User
{
    public int ID { get; set; }
    public string UserName { get; set; }

    public int TeamID { get; set; }
    public virtual Team Team { get; set; }
}
  

Я добавил эти биты в DbContext OnModelCreating() , как указано в сообщении в блоге, упомянутом выше:

 modelBuilder.Entity<User>()
    .HasRequired(u => u.Team)
    .WithMany()
    .HasForeignKey(u => u.TeamID);

modelBuilder.Entity<Team>()
    .HasRequired(t => t.Owner)
    .WithMany()
    .HasForeignKey(t => t.OwnerID)
    .WillCascadeOnDelete(false);
  

И теперь при добавлении данных, подобных этому:

 User u = new User();
u.UserName = "farinha";
Team t = new Team("Flour Power");
u.Team = t;
t.Owner = u;
context.Users.Add(u);
context.Teams.Add(t);
context.SaveChanges();
  

или даже вот так:

 User u = new User();
u.UserName = "farinha";
u.Team = new Team("Flour Power");
context.Users.Add(u);
context.SaveChanges();
  

Я получаю следующую ошибку:

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

Есть идеи, как это решить? Я сохраняю данные неправильным способом?

Заранее спасибо

Ответ №1:

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

 public class User
{
    public int ID { get; set; }
    public string UserName { get; set; }

    public int? TeamID { get; set; }
    public virtual Team Team { get; set; }
}
  

Затем вы должны сначала сохранить User объект, а затем вы можете сохранить Team .

 User u = new User();
u.UserName = "farinha";
context.Users.Add(u);
context.SaveChanges();

u.Team = new Team { Name = "Flour Power", OwnerID = u.ID };
context.SaveChanges();
  

Комментарии:

1. @ladislav-mrnka, из-за которого ошибка изменяется на Cannot insert the value NULL into column 'TeamID', table 'DeuceHigh.dbo.User'; column does not allow nulls. INSERT fails. The statement has been terminated.

2. @Farinha С тех пор, как ваша модель изменилась, ваша таблица базы данных тоже обновилась?

3. @Farinha: Это ошибка уровня базы данных, которая означает, что TeamID в таблице User по-прежнему не обнуляется. Вы не воссоздавали и не изменяли базу данных.

4. Я настроил EF на удаление и воссоздание базы данных при изменении модели, поэтому база данных создается заново, что должно привести к тому, что TeamID будет создано значение nullable. Бит в DbContext OnModelCreating() мог вызывать проблемы, поэтому я изменил User сущность на HasOptional(u => u.Team) , которая теперь вызывает «Оператор INSERT, конфликтующий с ограничением ВНЕШНЕГО КЛЮЧА «Team_Owner». Конфликт произошел в базе данных «DeuceHigh», таблица «dbo.User», столбец «ID»»

5. Я отредактировал свой ответ. Вы должны вручную настроить OwnerID в новой команде, потому что ваши два отношения независимы друг от друга.