Search code examples
c#linqasp.net-coreentity-framework-core

How to filter subqueries in Linq and Entity Framework Core


How can I filter the subqueries? When selecting Payment entities, I want to select where Active == true.

Expression:

public async Task<Invoice> InvoiceAsync(Expression<Func<Invoice, bool>> predicate) => await ExecSingleAsync(this.GetDbSet<Invoice>()
    .Include(inv => inv.Actions)
    .Include(inv => inv.Account)
    .Include(inv => inv.Customer)
    .Include(inv => inv.Payments)
        .Where(pm => pm.Active)
    .Include(inv => inv.Lines)
        .Where(ln => ln.Active)
    .Where(inv => inv.Active)
    .Where(predicate));

Invoice.cs:

public class Invoice : DbAssets, IInvoice
{
    public int BillingClientId { get; set; }
    public int? CustomerId { get; set; }
    public int AccountId { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual Account Account { get; set; }
    public IEnumerable<InvoiceLine> Lines { get; set; } = new HashSet<InvoiceLine>();
    public DateTime BillingDate { get; set; }
    public DateTime DueDate { get; set; }
    public IEnumerable<InvoiceAction> Actions { get; set; } = new HashSet<InvoiceAction>();
    public string? Message { get; set; }
    public int Nr { get; set; }
    public IEnumerable<InvoicePayment> Payments { get; set; } = new HashSet<InvoicePayment>();

    [NotMapped]
    public decimal Total => this.Lines.Sum(ln => ln.Sum);

    [NotMapped]
    public decimal TotalPaid => this.Payments.Sum(pm => pm.Amount);

    [NotMapped]
    public InvoiceStatus Status => this.TotalPaid >= this.Total ? InvoiceStatus.Closed : InvoiceStatus.Open;

    [NotMapped]
    public decimal Mva => this.Lines.Sum(ln => ln.Mva);
}

Payment.cs:

public sealed class InvoicePayment : DbAssets, IInvoicePayment
{
    public int InvoiceId { get; set; }
    public DateTime PaymentDate { get; set; }
    public decimal Amount { get; set; }
}

Both classes have an Active field.


Solution

  • public async Task<Invoice> InvoiceAsync(Expression<Func<Invoice, bool>> predicate) => await ExecSingleAsync(this.GetDbSet<Invoice>()
        .Include(inv => inv.Actions)
        .Include(inv => inv.Account)
        .Include(inv => inv.Customer)
        .Include(inv => inv.Payments.Where(p => p.Active))
        .Include(inv => inv.Lines)
        .Where(inv => inv.Active)
        .Where(predicate));