Home > Software design >  When to set Id and when to set Object
When to set Id and when to set Object

Time:11-26

I have the following entities:

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();
}

I try to add an Author and set the BookId to an existing value.

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

_dbContext.Authors.Add(author);

When I inspect the ChangeTracker to see what DbContext is going to do:

var longView = _dbContext.ChangeTracker.DebugView.LongView;

It indicates that Author, Book, and User will all be added.

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>

How can I do it so that only the new Author gets added when the BookId foreign key is set? Should I be setting objects instead of Ids?

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

CodePudding user response:

newAuthor.Book is not null and is not tracked by EF so it will consider it as a new book. There are multiple options:

  1. "Clear" the book object:
var newAuthor = new Author();
newAuthor.BookId = 1;
newAuthor.Book = null;
  1. Attach the book:
var newAuthor = new Author();
newAuthor.Book.Id = 1;
_dbContext.Books.Attach(newAuthor.Book);

_dbContext.Authors.Add(author);
  1. Fetch the book from database (as you have suggested yourself)

CodePudding user response:

Yes, don't modify the foreign keys directly, instead let ef core do its job by setting the object itself. Also don't new() reference navigation properties:

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

doing it for collection navigation properties is good because it avoids null exceptions when trying to add to the collection, for example.

  • Related