EFCore save entity with relation ids

asp.net-core c# entity-framework entity-framework-core

Question

I'm trying to save an entity, but this entity is related to another one and of this one I only have the id. For example, giving this structure:

public class Library
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Book> Books { get; set; }
}

public class Book
{
    public int Id { get; set; }
    public int LibraryId { get; set; }
    public string Title { get; set; }
    public Bookshelf Bookshelf { get; set; }
}

public class Bookshelf
{
    public int Id { get; set; }
    public string Color { get; set; }
}

I receive from the client a new book to save to the db. This book only contains the Title, the LibraryId and the BookshelfId (it's a DTO). Now I want to save this book, creating the relationship with Library and Bookshelf, without retrieving the full object Library and Bookshelf, how can I do it easily?

What if, for example, I want to create a new library, and relate it to some already existing books? What I should do to achieve it?

1
0
6/8/2019 8:59:56 AM

Accepted Answer

I want to save this book, creating the relationship with Library and Bookshelf, without retrieving the full object Library and Bookshelf

Simply add a property BookshelfId on your book class.

public class Book
{
    public int Id { get; set; }
    public int LibraryId { get; set; }
    public string Title { get; set; }
    public Bookshelf Bookshelf { get; set; }
    public int BookshelfId { get; set; }
}

Then you can do:

DbContext.Add(new Book { LibraryId = 1, BookshelfId = 1});
DbContext.SaveChanges();

What if, for example, I want to create a new library, and relate it to some already existing books

Add Library navigation property on the book

public class Book
{
    public int Id { get; set; }
    public Library Library { get; set; }
    ...
}

and then you can update the library property on the books using only their ids

var library = new Library { Name = "My library" };
DbContext.Libraries.Add(library);

var bookIds = new int[] {1, 2};

foreach(var bookId in bookIds) {
    var book = new Book { Id= bookId, Library = library};
    DbContext.Attach(book);
    DbContext.Entry(book).Property(b => b.LibraryId).IsModified = true;
}

DbContext.SaveChanges();
1
6/8/2019 11:36:39 AM

Popular Answer

This example I create a new library, new book shelf and new book without fetching any data.

My classes:

public class Library
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Book> Books { get; set; }
}

public class Bookshelf
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public string Color { get; set; }
}

public class Book
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public int LibraryId { get; set; }
    public string Title { get; set; }

    public int BookshelfId { get; set; }

    [ForeignKey("BookshelfId")]
    public virtual Bookshelf Bookshelf { get; set; }

    [ForeignKey("LibraryId")]
    public virtual Library Library { get; set; }
}

Saving new Book with new Library and new Bookshekf.

var contextDb = new LabContextDb();

var newLibrary = new Library()
{                
   Id = 1,
   Name = "My new library",
};

newLibrary = contextDb.Libraries.Add(newLibrary).Entity;

 var newBookshelf = new Bookshelf() { Id = 2, Color = "Blue" };

 newBookshelf = contextDb.Bookshelves.Add(newBookshelf).Entity;

 var newBook = new Book()
 {
    Id = 5,
    Title = "My New Book",
    LibraryId = newLibrary.Id,
    Bookshelf = newBookshelf
  };

 contextDb.Books.Add(newBook);
 contextDb.SaveChanges();

Expected result

enter image description here



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow