I want to have a table of Books, a table of Customers and a table of Loans. The Customers table should have a one to many relationship with the Loans table. The Books table should also have a one to many relationship with the Loans table.
In order to simulate this behavior, in my C# code I have declared the class Loan which has a field of type Customer object and another field of type Book object.
Because of this, in the database the Loan entity has (among others) two fields: one called CustomerID (of type int) and one called BookId(of type int).
There are cases in the code where I need to retrieve a list of all the loans that belong to a customer. When I do this, a list of Loans objects is returned indeed, but for each object, the fields CustomerID and BookId are null
. That is because in the database, EF Core stores them as int and in my C# code classes they are objects of type Customer and Book.
Is my approach of creating the tables wrong? And also what should be a solution to my problem? Thanks in advance, I am new to EF Core so any help would be appreciated.
Customer.cs
public class Customer : Person
{
public DateTime DateJoined { get; set; }
public bool Status { get; set; }
[Required(ErrorMessage = "Please enter a valid email!")]
public string Email { get; set; } = string.Empty;
[Required(ErrorMessage = "Please enter a valid password")]
[StringLength(20,ErrorMessage = "The password can contain up to 20 characters")]
[MinLength(5,ErrorMessage = "The password can be at least 5 characters long")]
public string Password { get; set; } = string.Empty;
}
Book.cs
public class Book
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string? ImageUrl { get; set; }
public string? Cathegory { get; set; }
public int PublicationYear { get; set; }
public int CopiesAvailable { get; set; }
public string Description { get; set; } = string.Empty;
public bool IsBookOfTheMonth { get; set; }
public Author Author { get; set; } = default!;
}
Loan.cs
public class Loan
{
public int Id { get; set; }
public DateTime DateBorrowed { get; set; }
public int Status { get; set; }
public Customer Customer { get; set; } = default!;
public Book Book { get; set; } = default!;
}
CodePudding user response:
You need to use Include
extension method to load related data:
var loans = context.Loans
.Include(loan => loan.Customer)
.Include(loan => loan.Book)
.ToList();
Use ThenInclude
extension method to include multiple levels of related data.
var loans = context.Loans
.Include(loan => loan.Customer)
.Include(loan => loan.Book)
.ThenInclude(book => book.Author)
.ToList();
These methods are located in the Microsoft.EntityFrameworkCore
namespace so to use them you need to add:
using Microsoft.EntityFrameworkCore;
https://learn.microsoft.com/en-us/ef/core/querying/related-data/eager
Also it is recommended to have a foreign key property defined in your entities:
public class Loan
{
public int Id { get; set; }
public DateTime DateBorrowed { get; set; }
public int Status { get; set; }
public int CustomerId { get; set; }
public Customer Customer { get; set; } = default!;
public int BookId { get; set; }
public Book Book { get; set; } = default!;
}