I have been trying for a while to find a suitable solution for a linq query I am trying to write.
In my model structure I have my Item class, which holds a list of PaymentRecords. What I want my query to achieve is:
public class PaymentRecord
{
public int PaymentRecordId { get; set; }
[Required]
public double PaymentAmount { get; set; }
[Required]
public DateTime DateOfPayment { get; set; }
[Required]
public bool FinalPayment { get; set; }
[JsonIgnore]
public Item Item{ get; set; }
}
public class Item
{
public int ItemId { get; set; }
public List<PaymentRecord> PaymentRecords {get; set;}
...various other properties
}
Select all Items, where the PaymentRecord list matches the condition below (which works fine), or where PaymentRecord is null e.g. the Items class has no PaymentRecord. Is there a way in which to do this?
var result = m_context.Item
.SelectMany(
x => x.PaymentRecords.Where(p => (p.FinalPayment == true
&& p.DateOfPayment >= _revenueStatementRequest.StartDate
&& p.DateOfPayment <= _revenueStatementRequest.EndDate)
|| p.FinalPayment != true),
(x, p) => x
)
.ToList();
Ideally I would like to do something like below, but I have not been able to get anything similar to work:
var result = m_context.Item
.SelectMany(
x => x.PaymentRecords.Where(p => (p.FinalPayment == true
&& p.DateOfPayment >= _revenueStatementRequest.StartDate
&& p.DateOfPayment <= _revenueStatementRequest.EndDate)
|| p.FinalPayment != true)
|| x.PaymentRecords == null,
(x, p) => x
)
.ToList();
After working from the answer given I have this:
m_context.Item.Where(c => (!
c.PaymentRecords.Any(q => (q.FinalPayment &&
q.DateOfPayment >= _revenueStatementRequest.StartDate &&
q.DateOfPayment <= _revenueStatementRequest.EndDate)
|| q.FinalPayment != true
)
)
&& (c..Type == Booked || c.Type == Reserved)
&& (c.StartDate < _revenueStatementRequest.StartDate)
)
Select and SelectMany are projection operators. A select operator is used to select value from a collection and SelectMany operator is used to selecting values from a collection of collection i.e. nested collection.
SelectMany experiences a NullReferenceException when selector returns null . This is undesirable because it's a confusing crash with a "forbidden" exception type in BCL code.
What best describes the SelectMany() Language Integrated Query (LINQ) extension method? It projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence.
SelectMany(<selector>) method The SelectMany() method is used to "flatten" a sequence in which each of the elements of the sequence is a separate, subordinate sequence.
You could do it without the SelectMany
List<Item> res = m_context.Items
.Where(c => !c.PaymentRecords
.Any(q => (q.FinalPayment &&
q.DateOfPayment >=_revenueStatementRequest.StartDate &&
q.DateOfPayment <= _revenueStatementRequest.EndDate)
|| !q.FinalPayment)
)
//**EDIT**
.Where(c => c.StartDate < _revenueStatementRequest.StartDate)
//this is comment out, so we can better test on the more complex part of the query
//.Where(c => c.Type == Booked || c.Type == Reserved)
.ToList();
that way you get a List<Item>
instead of List<PaymentRecord>
Select all Items, where the PaymentRecord list matches the condition below (which works fine), or where PaymentRecord is null e.g. the Items class has no PaymentRecord.
var result = m_context.Item
.Where(x => !x.PaymentRecords.Any() ||
x.PaymentRecords.Any(p => (p.FinalPayment == true
&& p.DateOfPayment >= _revenueStatementRequest.StartDate
&& p.DateOfPayment <= _revenueStatementRequest.EndDate)
|| p.FinalPayment != true))
.ToList();
I don't see any reason for using SelectMany
here. Simple Where
condition can do the work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With