I have an invoice object that has properties, among them a client object and a list of items. My goal is to retrieve a list of invoices from the database but every time I do that the invoices come back with null references assigned to their client objects and lists of items. Is there something wrong with my data model ?
Here's my data model:
public class Invoice
{
public string InvoiceId { get; set; } = GenerateID.GenerateInvoiceID();
public string Description { get; set; }
public List<InvoiceItem> Items { get; set; }
public DateTime InvoiceDate { get; set; }
public string PaymentTerms { get; set; }
public DateTime PaymentDue { get; set; }
public int TotalPrice { get; set; }
public string Status { get; set; } = "pending";
public Client Client { get; set; }
public string BillFromAddress { get; set; }
public string BillFromCity { get; set; }
public string BillFromCountry { get; set; }
public string BillFromPostal { get; set; }
}
public class Client
{
public string ClientId{ get; set; } = GenerateID.GenerateClientID();
[Required]
public string ClientName { get; set; }
[Required]
public string ClientEmail { get; set; }
[Required]
public string ClientAddress { get; set; }
[Required]
public string ClientCity { get; set; }
[Required]
public string ClientCountry { get; set; }
[Required]
public string ClientPostal { get; set; }
}
public class InvoiceItem
{
public string InvoiceItemId { get; set; } = GenerateID.GenerateItemID();
public string InvoiceId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int Quantity { get; set; }
[Required]
public int Price { get; set; }
public InvoiceItem()
{
}
public InvoiceItem(string itemName, int quantity, int price)
{
Name = itemName;
Quantity = quantity;
Price = price;
}
}
Here are the services that add and retrieve invoices:
public async void AddInvoice(InputModel input)
{
Invoice invoice = new Invoice();
invoice.Description = input.Description;
invoice.Items = input.Items;
invoice.InvoiceDate = input.InvoiceDate;
invoice.PaymentTerms = input.PaymentTerms;
invoice.Client = input.Client;
invoice.BillFromAddress = input.BillFromAddress;
invoice.BillFromCity = input.BillFromCity;
invoice.BillFromCountry = input.BillFromCountry;
invoice.BillFromPostal = input.BillFromPostal;
//Attaching the invoice id to each item in the invoice
foreach (var item in invoice.Items)
{
item.InvoiceId = invoice.InvoiceId;
}
_context.Add(invoice);
await _context.SaveChangesAsync();
}
public async Task<List<Invoice>> GetInvoices()
{
return await _context.Invoices.ToListAsync();
}
Here’s the DbContext class:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
public DbSet<Invoice> Invoices { get; set; }
}
Here are the records in the database:
CodePudding user response:
To be able to query the related entities such as Client
, InvoiceItem
of Invoice
, you need eager loading.
public async Task<List<Invoice>> GetInvoices()
{
return await _context.Invoices
.Include(x => x.Client)
.Include(x => x.Items)
.ToListAsync();
}
References