Когда устанавливать Id и когда устанавливать Object

У меня есть следующие сущности:

public class Book {
  public int Id { get; set; }
  public string Name { get; set; } = string.Empty;
  public int? AddedByUserId { get; set; }

  public virtual ICollection<Author> Authors { get; set; } = new HashSet<Author>();
}


public class Author {
  public int Id { get; set; }
  public int BookId { get; set; }
  public string Name { get; set; } = string.Empty;
  public int? AddedByUserId { get; set; }

  public Book Book { get; set; } = new Book();
}

Я пытаюсь добавить Author и установить существующее значение BookId.

var newAuthor = new Author();
newAuthor.BookId = 1;

_dbContext.Authors.Add(author);

Когда я проверяю ChangeTracker, чтобы увидеть, что собирается делать DbContext:

var longView = _dbContext.ChangeTracker.DebugView.LongView;

Это означает, что будут добавлены Author, Book и User.

Author {Id: -2147482646} **Added**
  Id: -2147482646 PK Temporary
  AddedByUserId: 1
  DateAdded: '11/25/2022 8:22:11 PM'
  Name: 'My Author Name'
  BookId: -2147482643 FK Temporary
  Book: {Id: -2147482643}
Book {Id: -2147482643} **Added**
  Id: -2147482643 PK Temporary
  AddedByUserId: -2147482645 FK Temporary
  DateAdded: '1/1/0001 12:00:00 AM'
  Name: ''
  AddedByUserId: {Id: -2147482645}
User {Id: -2147482645} **Added**
  Id: -2147482645 PK Temporary
  DateAdded: '1/1/0001 12:00:00 AM'
  Name: <null>
  RowVersion: <null>

Как я могу сделать так, чтобы при установке внешнего ключа Author добавлялся только новый BookId? Должен ли я устанавливать объекты вместо идентификаторов?

newAuthor.Book = _dbContext.Book.Find(1);

Возможно, вы захотите изменить отношение Book и Author на N:M, поскольку авторы могут писать несколько книг, а книги могут быть написаны несколькими авторами.

Progman 25.11.2022 22:26
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

newAuthor.Book не является нулевым и не отслеживается EF, поэтому он будет рассматривать его как новую книгу. Есть несколько вариантов:

  1. «Очистить» объект книги:
var newAuthor = new Author();
newAuthor.BookId = 1;
newAuthor.Book = null;
  1. Прикрепить книгу:
var newAuthor = new Author();
newAuthor.Book.Id = 1;
_dbContext.Books.Attach(newAuthor.Book);

_dbContext.Authors.Add(author);
  1. Получить книгу из базы данных (как вы сами предложили)

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

Da Ta 26.11.2022 16:22

Да, не изменяйте внешние ключи напрямую, вместо этого позвольте ef core выполнить свою работу, установив сам объект. Также не new() ссылайтесь на свойства навигации:

public Book Book { get; set; } = new Book();

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

Другие вопросы по теме